Seriennummer auf Gültigkeit überprüfen

Hallo zusammen.

Ich möchte ein Programm entwerfen, das an eine PHP-Datei, die auf einem entfernten Server liegt, Daten übermittelt.
Nun sollte das PHP-Script nur Daten annehmen, wenn Sie wirklich von dem Programm stammen.

Deshalb hab ich mir überlegt, dass das Programm bei jedem Start eine Seriennummer, UID, o.ä. generiert und diese von dem PHP-Script abgefragt wird. Wenn diese Seriennummer/UID gültig ist, wird das Script ausgeführt und wenn nicht, passiert nix.

Doch irgendwie steh ich auf dem Schlauch bzw bin nicht gut genug in Mathematik um das Ganze umzusetzen.

Ich weiß, dass ich die Seriennummer durch eine Prüfsumme auf Gültigkeit überprüfen könnte. Diese Prüfsumme könnte man an die Seriennummer anhängen.

Doch ich hab so gut wie keine Ahnung von Algorithmen und daher fällt mir das Ganze etwas schwer umzusetzen, sowohl mathematisch als auch programmiertechnisch.

In konkreten Fragen:
- Wie sollte ich am besten eine Seriennummer/UID generieren?
- Wie generiere ich eine Prüfsumme zu einer Seriennummer?
- Wie überprüfe ich diese Prüfsumme auf Gültigkeit?

Im Moment lasse ich die Seriennummer so generieren:
Code:
For i = 1 To 10
    wert1 = ((3 * id) + i) + wert1
    wert2 = (2 * id) + (id * i) + wert2
Next

sn = wert1 & id & "-" & wert2
Das Ganze soll in vb.net umgesetzt werden.

Es muss nicht sonderlich komplex oder aufwändig sein. Um Kollisionen oder ähnliches hab ich mir z.B. noch garkeine Gedanken gemacht. Das Ganze dient mehr dem Lerneffekt. :)

Ich hoffe, dass jmd einen Ansatz oder Tipps hat, wie ich so etwas am Besten umsetzen kann. Für Links zu dem Thema bin ich natürlich auch sehr dankbar. ;)

Beste Grüße
Knoxx
 
Ich verstehe dich nicht so richtig...

Original von Knoxx
Ich möchte ein Programm entwerfen, das an eine PHP-Datei, die auf einem entfernten Server liegt, Daten übermittelt.

Ja, soweit klar.

Nun sollte das PHP-Script nur Daten annehmen, wenn Sie wirklich von dem Programm stammen.

Die Daten werden vom Programm selbst erstellt, richtig?

Deshalb hab ich mir überlegt, dass das Programm bei jedem Start eine Seriennummer, UID, o.ä. generiert und diese von dem PHP-Script abgefragt wird. Wenn diese Seriennummer/UID gültig ist, wird das Script ausgeführt und wenn nicht, passiert nix.

Bist du sicher, dass du eine "Seriennummer" und nicht eher soetwas wie einen Schlüssel oder eine Prüfsumme meinst? Warum soll diese Nummer jedes mal beim Start neu generiert werden? Ist es immer dieselbe? Wenn nein, wovon hängt das ab? Wovor soll dieser Mechanismus Schutz bieten?

Soll das so in richtig "Hackit" gehen?
 
Hallo,
meinst du soetwas wie Einmalpasswörter?

Wenn ich dich richtig verstanden habe:
Dein Script sendet Daten an einen PHP Script. Dieser PHP Script soll die Daten nur annehmen, wenn das Programm außerdem eine gültigen Code (ein Passwort) mitsendet?


Dafür wären Einmalpasswörter ideal geschaffen. Nun gibt es verschiedene Möglichkeiten es zu realisieren, eine Lösung wäre, dass man eine Art Challenge-Response System nutzt.


Programm ruft Script A auf, Script A gibt einen Wert aus der DB zurück.
Programm berechnet dann sha1("geheimes_passwort"+wert_von_script_a) und sendet dies dann Script B.
Script B überprüft, ob es stimmt. Wenn ja, wird der Wert in der DB zufällig geändert.

Probleme gäbe es nur bei gleichzeitigen Zugriff über mehrere Instanzen.


Ansonsten könnte man die Daten auch ganz normal verschlüsseln und übersenden und das PHP Script testet dann ob die Daten valide sind.
 
Danke erstmal für eure Antworten. :)

Ich habe mich wohl etwas missverständlich ausgedrückt. Ich versuche nochmal zu erklären was genau ich machen will und wo dabei mein Problem liegt.

Ich habe mit VB.NET eine WindowsForm zusammengebastelt. Dort kann ich Name, Straße, Ort usw eingeben und das ganze soll an ein PHP-Script übermittelt werden.

Nun könnte auch ein Dritter mittels HTML ein Formular erstellen, welches die Daten an dieses PHP-Script sendet. Solche Vorgehensweisen möchte ich verhindern.

Das .net-Programm soll also einfach eine Variable an das PHP-Script mit übergeben, die eine vorher generierte ID, Seriennummer oder Schlüssel beinhaltet. Dieser Schlüssel soll nun von dem PHP-Script überprüft werden ob er richtig ist oder nicht.
Wenn der Schlüssel korrekt ist, verarbeitet das Script die Daten weiter.

Mein Problem liegt einzig und allein darin einen Algorithmus zu finden, mit dem ich Schlüssel und die dazu passende Prüfsummen erstellen kann.

Dann würde ich die Prüfsumme an diesen Schlüssel anhängen lassen und das PHP-Script errechnet mit dem selben Algorithmus die Prüfsumme und vergleicht. Wenn die Prüfsummen übereinstimmen, verarbeitet es die Daten und wenn sie unterschiedlich sind bricht es ab.

@Elderan:
Die Idee mit den Einmalpasswörtern geht schon in die Richtung, aber ich glaub ein Challenge-Response-System ist dafür etwas überdimensioniert.
Dieses Programm dient mehr dem Lerneffekt und ein einfacher "Schlüssel" der durch eine Prüfsumme überprüft wird, sollte doch eigentlich als kleiner Schutz ausreichen.
Ich hänge ja schon bei der Erstellung dieser Algorithmen...^^
 
Original von Knoxx
Danke erstmal für eure Antworten. :)

Ich habe mich wohl etwas missverständlich ausgedrückt. Ich versuche nochmal zu erklären was genau ich machen will und wo dabei mein Problem liegt.

Ich habe mit VB.NET eine WindowsForm zusammengebastelt. Dort kann ich Name, Straße, Ort usw eingeben und das ganze soll an ein PHP-Script übermittelt werden.

Nun könnte auch ein Dritter mittels HTML ein Formular erstellen, welches die Daten an dieses PHP-Script sendet. Solche Vorgehensweisen möchte ich verhindern.

Das .net-Programm soll also einfach eine Variable an das PHP-Script mit übergeben, die eine vorher generierte ID, Seriennummer oder Schlüssel beinhaltet. Dieser Schlüssel soll nun von dem PHP-Script überprüft werden ob er richtig ist oder nicht.
Wenn der Schlüssel korrekt ist, verarbeitet das Script die Daten weiter.

Mein Problem liegt einzig und allein darin einen Algorithmus zu finden, mit dem ich Schlüssel und die dazu passende Prüfsummen erstellen kann.

Okay, versteh ich schon eher (hoffe ich). Wenn dir Elderans Lösung nicht gefällt, hier eine Alternative:

Du erstellst zuerst eine Prüfsumme der Daten. Dafür kannst ja MD5, SHA-X oder sonstwas nehmen. Du kannst dir natürlich auch eine eigene völlig unsichere Hashfunktion schreiben.

Zum Beispiel wählst du zuerst einen immer gleichen Wert (z.B. 28365239082374) am besten in einer länge wie 256bit oder sowas. Dann teilst du deine Daten, die von deinem Script gesendet werden in 256bit große Blöcke ein und füllst den letzten Block ggf. auf.
Nun kannst du z.b. deinen am Anfang gewälten werden XOR mit dem ersten Block nehmen, dann mit dem zweiten addieren und modulieren (also Modulo 128bit nehmen, keine Ahnung wie das richtige Verb heißt), dann wieder XOR nehmen und so weiter.
Oder du nutzt andere Operatoren, da kannst du deine Kreativität freien Lauf lassen. Produktiv solltest du das dann aber nicht einsetzen.

Dann verschlüsselst du die somit erstellte Prüfsumme nach einem symmetrischen (oder besser asymmetrischen) Verfahren.
RSA würde hier z.B. in Frage kommen, das ist auf Wikipedia auch ganz gut erklärt, aber auch nicht so einfach zu implementieren (bzw. ohne Lerneffekt). Auch hier kannst du dir z.B. eine einfache auf XOR basierende symmetrische Verschlüsselung überlegen.
Den Schlüssel brauchen dann (bei Symmetrie) sowohl das Programm als auch das Script. Naja und der Rest sollte klar sein oder?
 
Irgendwie reden wir glaub ich an einander vorbei. Oder ich denke mir, das zu einfach... ^^

Wie machen das z.B. alle anderen Programme mit Seriennummern? Man gibt eine Seriennummer ein und das Programm überprüft ob die Serial korrekt ist. Vom Prinzip ist das doch daselbe was ich vorhabe. Das .net-Programm erstellt eine Seriennummer/Schlüssel/ID und das PHP-Script überprüft ob diese korrekt ist.

Nur wie baue ich den Algorithmus auf, damit so etwas möglich ist?
Ich habe mir überlegt, einfach eine lange "Zufallszahl" zu generieren und daraus mit einem Prüfalgorithmus eine Prüfsumme berechnen lassen, die dann nochmal in diese lange "Zufahlszahl" eingebaut wird.

Das PHP-Script extrahiert dann die Prüfsumme und berechnet mit dem gleichen Prüfalgorithmus die übrige Zahl und vergleicht die beiden Prüfsummen.

Ich schau mal ob ich so weiterkomme. :)
 
Original von Knoxx
Irgendwie reden wir glaub ich an einander vorbei.

Ja, weil du deine Ziele ständig änderst!
Zuerst hieß es doch
Ich möchte ein Programm entwerfen, das an eine PHP-Datei, die auf einem entfernten Server liegt, Daten übermittelt.
Nun sollte das PHP-Script nur Daten annehmen, wenn Sie wirklich von dem Programm stammen.
und nun:
Wie machen das z.B. alle anderen Programme mit Seriennummern? Man gibt eine Seriennummer ein und das Programm überprüft ob die Serial korrekt ist. Vom Prinzip ist das doch daselbe was ich vorhabe. Das .net-Programm erstellt eine Seriennummer/Schlüssel/ID und das PHP-Script überprüft ob diese korrekt ist.

Das ist aber etwas anderes, das ist nicht dasselbe. In dem Fall, den du zuerst beschrieben hast, war von "Eingaben durch den Benutzer" gar keine Rede.

Beschreib nochmal ganz _konkret_ am besten mit einem möglichst wenig abstrakten Beispiel, was genau du vorhast. Und bitte _nicht_ mit möglichen Lösungsansätzen oder Vermutungen vermischen. Sonst ist das nämlich nur ein Herumgerate.
(Ein Beispiel für ein Programm, was einen gleichen oder ähnlichen Mechanismus enthält, wäre sehr sehr hilfreich)
 
Hallo,
also das Problem mit der Seriennummer ist ein ganz anderes. Bei Seriennummern muss man einen eigenen Algorithmus entwerfen, der die Seriennummer überprüft und insbesondere muss man diesen Algortihmus sehr gut schützen.

Du kannst aber auf bekannte Algorithmen zurückgeifen, ergänzt diese durch einen geheimen Paramater, fertig.


Eine einfache Lösung wäre eine MAC, dies geht ganz einfach:
sha1("mein super geheimes passwort"+$daten_die_man_senden_moechte);

Dein Client geniert diese MAC ( sha1(key + daten) ) und sendet diese mit den Daten an dein PHP Script. Dein PHP Script überprüft dann, ob das Hash Wert (die MAC) zu den Daten passt.
Nur wer dein Passwort kennt, könnte eigene MACs erstellen. Allerdings ist dieses Verfahren nicht gegen Replay Attacken geschützt, die Daten könnte man immer wieder an das Script senden, auch wenn man dein PW nicht kennt.

Evt. reicht dies schon für deine Bedürfnisse.

Eine Alternative wäre mit der Zeit zu arbeiten:
sha1("geheimes passwort"+time());

Das VB.net Prog. sendet den aktuellen Timestamp und eben sha1(key+timestamp);

Im PHP Script wird überprüft, ob der Timestamp nicht zu alt ist (gegen Replay Attacken) und dann wird entsprechend der Hashwert überprüft.

Problem: Funktioniert nicht, wenn die Uhr am Computer stark falsch geht.
 
Ich glaube wir kommen der Sache näher... also weiterhin vielen Dank für eure Bemühungen. :)
Das mit den MACs geht schon in die richtige Richtung. Aber es ist noch nicht 100%, das was ich will.

Zuerst einmal: Ich werde das PHP-Script wohl über HTTPS aufrufen. Somit is die Verschlüsselung erst einmal gewährleistet. Mir geht es um die Authentifizierung des Programmes.
Dazu soll er beim Start automatisch einen Schlüssel oder UID erzeugen, den mit übermitteln und der Schlüssel bzw UID wird dann vom PHP-Script geprüft, ob er valide ist.
Dieses Verfahren möchte ich gerne selbst schreiben um die Vorgehensweise solcher Authentifizierungen besser zu verstehen.

Ein ganz einfaches Beispiel:

Das vb.net-Programm generiert seinen Schlüssel
Code:
'rand ist eine gerade zufallszahl
For i=1 To 10
  key=rand*i
Next
Da ja nun die gerade Zufallszahl beim letzten Schleifendurchlauf mit 10 multipliziert wurde, ergibt eine Division durch 10 also auch immer eine gerade Zahl. Dies könnte mein PHP-Programm überprüfen.
Sendet ein Dritter dann den Keystring "3333" mit, würde das PHP-Script erkennen, dass es kein gültiger Schlüssel ist.

So in etwa hab ich mir das gedacht...^^
Nur ist dieses Beispiel etwas "einfach", aber ich hab keinen Schimmer wie ich das nun sicherer bzw besser programmieren könnte. Mir fehlt dazu scheinbar einfach das mathematische und programmiertechnische Hintergrundwissen.
Daher wollte ich fragen ob jemand für diese Algorithmen-Erstellung einen Tipp oder Hinweis hat oder ob ihr vielleicht sonstige Quellen kennt, wo ich mich etwas mehr in diese Thematik einarbeiten kann?

Ich will also nicht die Daten verschlüsseln oder die Daten signieren o.ä., ich möchte einen mehr oder weniger eindeutigen Schlüssel beim Programmstart generieren lassen und dieser Schlüssel dient sozusagen zur Authentifizierung des vb.NET-Programms an dem PHP-Script.

Entschuldigt bitte, dass ich mich evtl. so "unklar" auszudrücke. Ich hab von dieser Thematik kaum eine Ahnung und daher weiß ich nicht, wie ich mein Problem eindeutig beschreiben soll. Ich versuche ja so präzise wie möglich zu sein, jedoch fehlt mir dazu etwas das Verständnis für diese Algorithmen- und Krypto-Sachen. >.<
 
Hallo,
und was ist an einer MAC auszusetzen? Nur dein Programm sollte den Key kennen und somit kann sich nur dein Programm authentifizieren.

Ansonsten nutzt man für Authenfizierung i.d.R. Challenge-Response.
 
Außerdem könntest du bei deinem Verfahren direkt einen statischen Key verwenden, da du sowieso nirgendwo sicherstellst, dass nicht immer der gleiche Key verwendet wird. Bei den MACs würde das verhindert, da der Key entweder von den Daten oder der Uhrzeit abhängig wäre.
 
Also, mein vb.net-Programm generiert aus einem PW und dem aktuellen Timestamp einen Hashwert und hängt den Timestamp nochmal an den Hashwert an. Dieser String wird nun mit übermittelt an mein PHP-Script und wird dort zerlegt. Dann generiert das PHP-Script auf dieselbe Art und Weise einen Hashwert und vergleicht beide. Hab ich das nun richtig verstanden?

Wenn ja, wäre es durch aus eine Lösung für mein Problem.
Allerdings ging meine ursprüngliche Idee in die Richtung mit diesen Seriennummern.

Original von Elderan:

also das Problem mit der Seriennummer ist ein ganz anderes. Bei Seriennummern muss man einen eigenen Algorithmus entwerfen, der die Seriennummer überprüft und insbesondere muss man diesen Algortihmus sehr gut schützen.

Du kannst aber auf bekannte Algorithmen zurückgeifen, ergänzt diese durch einen geheimen Paramater, fertig.
Mir ging es um solche Algorithmen und die spätere Überprüfung durch Prüfsummen. Solche Verfahren könnte man doch auch für mein Problem einsetzen, oder sehe ich da was falsch?
vb.net-Programm generiert jedesmal vorm senden eine neue Seriennummer, diese wird übermittelt und von dem PHP-Programm über eine Prüfsumme auf Gültigkeit geprüft.

Hast du vielleicht ein paar Links zu diesem Thema?

EDIT:
Ich werde für mein Programm wohl wirklich die Variante mit den sha1-Hash aus PW und Timestamp verwenden, da es scheinbar die bessere Lösung ist. Vielen Dank dafür. :)
Allerdings interessiere ich mich immernoch für die Erstellung von Seriennummern/UID/usw. Daher hoffe ich, dass mir noch jmd einen Tipp oder Link diesbezüglich geben könnte. Bei meinen Google-Ergebnissen habe ich zwar 1001 Keygen-Me's gefunden, aber keine Quellen die sich wirklich mit der Erstellung von solchen Algorithmen befassen.
 
Prüfsummen/ziffer

Hier ein Beispiel in C, wie die Berechnung einer Prüfzifer für eine 9stellige Nummer aussehen kann:

Code:
/****************************************************************************
 * pruefziffer.c                                                            *
 *                                                                          *
 * Berechnet eine Prüfziffer für eine neunstellige Kontonummer oder prüft   *
 * eine 10stellige Kontonummer inklusive Prüfziffer.                        *
 *                                                                          *
 * Aufruf:                                                                  *
 * pruefziffer 123456789    // 9stellige Kontonummer, berechne Prüfziffer   *
 * pruefziffer 1234567890   // 10stellige Kontonummer, prüfe Prüfziffer     *
 ****************************************************************************/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>

/******************************************************************************/
int berechne_pruefziffer(char *s)
{
	int t;    // Schleifenindex
	int sum;  // Zwischensumme
	int pz;   // Die berechnete Prüfziffer
	int a;    // Zwischenfeld
	int geheim[9]={5,3,7,9,1,4,2,6,8}; // Wichtig! Keine doppelten Ziffern!!
	// mit geheim[] kann man den Algorithmus individuell anpassen

	sum=0;                 // Zuerst wird eine Summe gebildet.
	for(t=0; t<9; t++){    // über die 9 Stellen der Kontonummer
		a=s[t]-'0';         // Achtung!! Das funktioniert nur mit ASCII
		a=a*geheim[t];      // Multipliziere mit dem geheimen Faktor
		a=a%10;             // Modulo 10, nur Werte von 0-9
		sum=sum+a;          // und aufsummieren
	}

	pz=0;                  // Jetzt machen wir aus der Summe eine Ziffer
	for(;;){
		if(sum==0) break;   // Summe = 0? Abbruch
		a=sum % 10;         // Letzte Dezimalstelle der Summe holen
		pz=pz+a;            // und aufaddieren
		sum=sum/10;         // Letzte Dezimalstelle der Summe entfernen
	}
	pz=pz%10;              // Prüfziffer Modulo 10 = Wert von 0-9
	return(pz);            // Prüfziffer zurückgeben
}
/******************************************************************************/
void pruefe_pruefziffer(char *s)
{
	int a;               // Zwischenfeld numerisch
	char zwi[32];        // Zwischenfeld char
	int pz;              // Prüfziffer

	strcpy(zwi, s);      // 10stellige Kontonummer kopieren
	pz=zwi[9]-'0';       // Die übergebene Prüfziffer extrahieren
	zwi[9]=0;            // Kontonummer auf 9 Stellen reduzieren

	a=berechne_pruefziffer(zwi); // Prüfziffer berechnen
	if(a==pz){           // Stimmt die mitgegebene Prüfziffer?
		puts("Kontonummer ist in Ordnung.");
	}
	else{
		printf("Kontonummer ist FALSCH, Prüfziffer sollte %d sein.\n", a);
	}
}
/******************************************************************************/
int main(int argc, char **argv)
{
	int l;
	int a;

	if(argc <2){
		fprintf(stderr, "Kontonummer fehlt...\n");
		exit(1);
	}
	
	l=strlen(argv[1]);
	switch(l){
	case 9:
		a=berechne_pruefziffer(argv[1]);
		printf("Prüfziffer=%d >%s%d<\n", a, argv[1], a);
		break;
	case 10:
		pruefe_pruefziffer(argv[1]);
		break;
	default:
		fprintf(stderr, "Kontonummer muß 9 oder 10stellig sein...\n");
		exit(2);
	}
}

Zu einer 9stelligen Nummer wird eine einstellige Prüfziffer gebildet, sodaß eine 10stellige Nummer entsteht.

Wer den Algorithmus nicht kennt, kann die Prüfziffer durch 10maliges Raten natürlich rauskriegen, deswegen könnte man die Prüfziffer auch 2 oder 3stellig machen. Sofern man weiß, daß sich am Ende eine Prüfziffer befindet, natürlich..

Und gegen vermehrte falsch eingegebene Nummern kann man sich ja schützen.

Nach 3maligem Fehlversuch wird die Karte eingezogen, wie beim Geldautomaten :D

Hoffe, es hilft ein wenig.
 
Zurück
Oben