Wie man Seriennummern generieren kann
Bei Projekten, die nicht gegen vorab erstellte Schlüssel verifiziert werden können oder sollen verwendet man in der Regel Seriennummern oder Lizenz-Schlüssel.
Wie man solche auf einfache Weise für eigene Projekte erzeugen kann möchte ich hier vorstellen.
Hash vs. Serial
Erstmal eine kleine Einführung zum Thema Verschlüsselung.
Ein Hash ist das Ergebnis einer sog. Einwegfunktion, also einer Funktion die keine Umkehrung hat. Man kann das Ergebnis demnach nicht durch die Umkehrfunktion auf die Eingabe schließen.
Um einen Hash zu verifizieren ist es also nötig, den bekannten Hashwert mit dem Hash-Ergebnis einer Eingabe zu vergleichen. Eine typische Methode um eine Passwortabfrage durchzuführen.
Im Endeffekt ist ein Lizenz-Schlüssel nichts anderes als – wie der Name schon andeutet – eine Folge von Zeichen oder Ziffern die gegen einen bestimmten Algorithmus verifiziert wird. Wenn der Schlüssel durch den Algrithmus wie erwartet aufzulösen ist, dann ist er gültig. Es muss also kein Vergleich mit einem gespeicherten Wert durchgeführt werden, da der Schlüssel in sich selbst auflösbar sein muss.
Der Algorithmus
Für einen Schlüssel müssen wir uns also einen mehr oder weniger komplexen Algorithmus überlegen.
Der Nachteil an dieser Methode ist natürlich, dass diese Funktion geheim bleiben muss, denn sobald diese bekannt ist, lassen sich beliebig viele gültige Schlüssel von jedem der den Algorithmus kennt.
Für das Format des Schlüssels sind im Prinzip keine Grenzen gesetzt, jedoch ist klar, dass die Länge darüber entscheidet wie viele mögliche Schlüssel sich erzeugen lassen und wie komplex – also erratbar – er ist.
Den Schlüssel erzeugen
Für dieses Beispiel soll der Schlüssel aus vier jeweils vierstelligen Ziffern bestehen.
Um sicher zu stellen, dass die Formatvorgabe eingehalten wird ist der Modulo-Operator (mal wieder) ideal, da das Ergebnis, bzw. die Länge dessen, durch den Operator selbst bestimmt wird.
Listing 1
public function generateNumber(){ //einen zufälligen Startwert erzeugen $part1 = rand(1000, 9999); //Zweite Zahlengruppe aus dem Ergebnis der ersten mit angehängtem Zufallswert $part2 = ($part1 % 9).rand(100,999); //Dritte Zahlengruppe aus dem Ergebnis der zweiten mit angehängtem Zufallswert $part3 = ($part2 % 3).rand(100,999); //vierte Zahlengruppe aus dem Ergebnis der dritten mit angehängtem Zufallswert $part4 = ($part3 % 4).rand(100,999); //Rückgabe der Zahlengruppen mit '-' als Trennzeichen return sprintf("%04d-%04d-%04d-%04d",$part1,$part2,$part3,$part4); }
Den Schlüssel validieren
In diesem Beispiel ist der Schlüssel genau dann gültig, wenn die erste Ziffer der jeweiligen Zahlengruppe aus dem Ergebnis der vorherigen berechnet werden kann.
listing 2
public function validateNumber($number){ //Trennzeichen entfernen $parts = explode('-',$number); //Längenvalidierung (es müssen genau 4 Zahlen sein) if(sizeof($parts) != 4) return false; list($part1, $part2, $part3, $part4) = $parts; // Ergebnis 1. Zahl mit erster Stelle 2. Zahl vergleichen if($part1 % 9 != (int)substr($part2, 0, 1)) return false; // Ergebnis 2. Zahl mit erster Stelle 3. Zahl vergleichen if($part2 % 3 != (int)substr($part3, 0, 1)) return false; // Ergebnis 3. Zahl mit erster Stelle 4. Zahl vergleichen if($part3 % 4 != (int)substr($part4, 0, 1)) return false; // Berechnung hat funktioniert - Schlüssel gültig return true; }
Kommentare: 3
Eine kurze aber sehr gute Einstiegseinleitung in das Thema Serienummern. DANKE!
Hab gerade ein kleines Problem entdeckt. Die Seriennummer 0000-0000-0000-0000 ist leider auch richtig. Gegen solche Kollisionen sollte man vielleicht noch einen kleinen Schutz einbauen ;)
Da ist durchaus etwas dran. Danke für den Hinweis!