Autor Beitrag
Popov
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: Do 10.07.03 02:13 
PersNum ist ein kleines Programm mit dem man die Nummer eines deutschen Personalausweises auf Gültigkeit überprüfen kann. Weil das alleine nicht witzig ist, ist der Quellcode natürlich mit dabei. Wer also eine Prüfroutine für Personalausweise schreiben muß, der kann sich den Quellcode angucken. Die Prüfungsroutine für die Prüfsummen ist in einer extra Unit.

Das ganze beruht auf dem allgemein zugänglichen und offenem Algorithmus zu Berechnung der Prüfsummen für Personalausweise.

Direktlink:

www.popov.de.ms/pub/persnum/persnum.zip

Pagelinks:

www.popov.de.ms/pub (auf PersNum klicken und dann downloaden)

free.pages.at/popov3/pub (auf PersNum klicken und dann downloaden)
mitglied.lycos.de/popov3/pub (auf PersNum klicken und dann downloaden)

_________________
Popov
Luncustaf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 324

Win 2k
D7 Ent.
BeitragVerfasst: Do 10.07.03 10:12 
easy sieht lustig aus :)

nur das datumer kennter nicht ;)


gr€€tz
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 10.07.03 11:26 
Überprüf mal diese Perso-ID mit deinem Programm:
4417231730D<<7408317<0402187<<<<<<<8
Dein Eingabemaske stimmt auch nicht ganz.
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 10.07.03 12:28 
Ich habe für beide Fälle (Datum und falsche P-Nummer) die Lösung, denke ich.

@Popov: Ich bin der Meinung, dass du einen Gedankenfehler drin hast. Ich gehe mal davon aus, dass du das Programm vor der Veröffentlichung mit deiner eigenen Ausweisnummer überprüft hast. Wenn das Ergebnis bei dir richtig war, dann dürfte das ein toller Zufall gewesen sein, denn meine Ausweisnummer ist laut deinem Programm ungültig.

Der Denkfehler dürfte folgender sein: zur Berechnung der Einzelprüfziffern verwendest du das Array mit den 3 Werten (7,3,1). Weil die Blöcke aus 9 bzw. zweimal 6 Ziffern bestehen, landet man nach der Multiplikation eines Blocks immer wieder am Anfang des Arrays (auf der 7 also).
Beispiel, eine fiktive Behördenkennzahl und Nr.
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
1 * 7 =  7 =   7
2 * 3 =  6 =  13
3 * 1 =  3 =  16
4 * 7 = 28 =  44

1 * 3 =  3 =  47
2 * 1 =  2 =  49
3 * 7 = 21 =  70
4 * 3 = 12 =  82
5 * 1 =  5 =  87
----------------
               7

Sofern ich mich nicht verrechnet habe, sollte also die Einzelprüfsumme dieses Blocks eine 7 ergeben, die auch im ersten gelben Feld stehen müsste.

Um nun aber die Gesamtprüfsumme zu errechnen, müsstest du die eben ermittelte Einzelprüfsumme mit einfließen lassen. Bei der 7 hieße das also
ausblenden Quelltext
1:
7 * 7 = 49 = 136					

usw. Dadurch verschiebt sich nun aber auch die Gewichtung. Das heißt: die erste Ziffer aus dem Geburtstagsbock wird nicht mehr (wie bei der Einzelprüfsumme) mit 7 sondern jetzt mit 3 multipliziert, usw.

Du musst also in zwei Schritten vorgehen. Im ersten Schritt ermittelst du die Einzelprüfsummen, und im zweiten Schritt wiederholst du alles, baust aber nach den einzelnen Blöcken die Einzelprüfsummen mit ein.
Dadurch erhältst du am Ende die korrekte Prüfziffer. Das habe ich mit einem kleinen Tool und eigenem Algo ausprobiert, mit dem mein Ausweis dann auch wieder gültig ist. :) @Luckie: Mit meiner Routine ist die Nummer, die du zeigst, auch gültig. :wink:

btw: Der Algo lässt sich in dem Schema anhand des Beispiels ja sehr gut nachvollziehen. Wenn gewünscht, poste ich meine Funktion.

Und zum Datumsproblem, das bei mir auftrat: Nicht jeder benutzt Punkte im Datumsformat. Meins sieht so aus: YYYY-MM-TT. Du solltest daher vor deiner Berechnung
ausblenden Delphi-Quelltext
1:
DateSeparator := '.';					

aufrufen, sonst gibt es bei "StrToDate" eine Exception, weil angeblich das Datum ungültig ist.


Und zum Schluss: die Dialogs-Unit ist in deiner uNummerPruefen-Unit unnötig. Und du könntest deine Prüffunktionen (IsValidDate, IsValidDateStr,IsNum) vereinfachen. Die SysUtils bietet z.B. mit "IsLeapYear" eine Schaltjahres-Funktion an, und "IsNum" ist so einfacher:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function IsNum(S: String): Boolean;
var
  i, errCode : Integer;
begin
  Val(S,i,errCode); Result := (errCode = 0);
end;


Gruß.
Popov Threadstarter
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: Do 10.07.03 16:32 
Viele dank Leute, daß ihr mich für einen Trotel haltet, daß Schnellschüsse veröffentlicht. Das Programm ist korrekt und funktioniert auch. Allerdings muß ich zugeben, daß sich paar kleine Fehler eingeschlichen die nicht sofort erkennbar waren. Aber der Reihen nach:

@Luncustaf

Das Datum wird nicht erkannt.

Ja, das kommt dadurch, daß im Ausweis das Datum das YYMMDD Format hat. Delphi kennt das DDMMYY Format (Standardeinstellung). Ich hab das falsch ausgelesen und an einer Stelle Tag und Jahr vertausch. Dadurch konnte passieren, daß es plötzlich den 74 Feb. 03 gab. Ok, der Fehler ist beseitigt. Anscheinend hab ich beim Testen mit Zahlen gearbeitet die kleiner 12 waren. Dadurch ist der Fehler nicht aufgefallen.

Der zweite Datumsfehler ist ... naja. Ok, er ist da. Es handelt sich hier um das Geburtsdatum. Für Delphi ist eine Zweistelliges Jahr (also YY) ein Jahr aus dem aktuellen Jahrhundert. Also ist das Geburtsdatum 74 für Delphi jetzt nicht 1974, sondern 2074. Somit wurde 74 als Datum der Zukunft gedeutet. Ich hab diese Überprüfung ganz entfernt, da ich sowieso das Alter nicht prüfen wollte. Allerdings baue ich vielleicht später eine neue Überprüfung rein. Problematisch ist nicht das Jahr 74 als Geburtsdatum, sondern 01. Es kann 1901 und 2001 beduten. Da muß eben eine kleine Logik eingebaut werden.

@Luckie

Die Eingabemaske stimmt nicht ganz.

Die stimmt schon. Allerdings hab ich bemerkt, daß sich die Nummer um eine Zeichen erhöht hat, und zwar um ein "<". Ob das jetzt neu ist, weiß ich noch nicht. In allen mir bekannten Dokmenten darüber (auch offiziellen), ist der letzte Platzhalter 6 Zeichen lang. Vielleicht hat man ihn jetzt um ein Zeichen erhöht. Ich werde es nachprüfen. Allerdings hat das kein Einfluß auf die Eingabemaske selbst. An den Nicht-Platzhaltern hat sich nichts verändert.

@MathiasSimmack

Auch du Brutus?

Gedankenfehler.

Nein, da ist kein Gedankenfehler. Die Prüfung wird korrekt durchgeführt. Wenn du dir den Code ansiehst, dann wirst du feststellen, daß zuerst die erste Zahlenreihe geprüft wird, dann die zweite, dann die dritte und zum Schluß alles zusammen. Bei der letzten Überprüfung wurden die drei kleinen Prüfsummen mit einbezogen. Ich habs also schon richtig berechnet. Hätte ich es nicht gemacht, dann würde ich mich in dem Forum nie wieder blicken lassen. So ein Fehler wäre unverzeilich. Wieso es nicht funktionierte steht oben. Es waren nur die Datumsfehler die ich zum Schluß noch schnell eingebaut habe. Anscheinend zu schnell. Aber ich dachte mir, daß man auch das Geburts und Ablaufdatum prüfen sollte.

Bei den Code den du geschrieben hast, hast du wahrscheinlich nur die Prüfsummen berechnet, aber nicht überprüft ob es nur Zahlen sind oder das Datum logisch ist. Aber in meinem Programm wird sowas überprüft. Es ist also nicht nur eine Überprüfung, sonder mehrere, bzw. wird überprüft ob die Werte Unsinn enthalten.

Das mit dem DateSeparator war ein guter Tip und ich hab das eingebaut.

Das mit der Unit-Dialogs ist noch ein Überbleibsel meine ShowMessage Meldung die ich dann entfernt habe. Die Unit habe ich dabei vergessen.

Das mit dem IsLeapYear ist ein gutter Tip, aber er würde den Code kaum verkürzen. So aber sieht man wenistens, daß ich die Überprüfung auch von hand behersche ;)

Und zum Schluss: die IsNum Funktion. So Schlau bin ich auch. Nur vergißt du hier, daß die Val Variante auch "-" Minus akzeptiert und nur Zahlen bis Max-LongInteger. Wenn ich aber die letzte Prüfsumme berechne, dann hab ich eine Zahlenkette von 24 Zahlen. Das past nicht in einen Integer. Es mußte also eine extra Routine her ;)

_________________
Popov
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 10.07.03 17:11 
Popov hat folgendes geschrieben:
Viele dank Leute, daß ihr mich für einen Trotel haltet, daß Schnellschüsse veröffentlicht.

Es hat niemand das Wort Trottel benutzt. Ich war nur der Meinung, du hättest einen Fehler gemacht. Fehler können jedem passieren. Und Tatsache ist nun mal, dass auch nach dem "Patchen" deiner ersten Version (s. DateSeparator) meine Ausweisnummer als fehlerhaft bemängelt wurde.

Zitat:
Auch du Brutus?

:mrgreen:

Zitat:
Das mit dem IsLeapYear ist ein gutter Tip, aber er würde den Code kaum verkürzen. So aber sieht man wenistens, daß ich die Überprüfung auch von hand behersche :wink:

Code verkürzen? Dazu müsstest du auf die SysUtils-Unit verzichten. In der steckt aber auch "IsLeapYear" ... und die sieht etwas anders aus als dein
Zitat:
ausblenden Delphi-Quelltext
1:
(Frac(yy / 4)					

:wink:

Zitat:
Und zum Schluss: die IsNum Funktion. So Schlau bin ich auch. Nur vergißt du hier, daß die Val Variante auch "-" Minus akzeptiert und nur Zahlen bis Max-LongInteger. Wenn ich aber die letzte Prüfsumme berechne, dann hab ich eine Zahlenkette von 24 Zahlen.

Siehst du. Das Problem habe ich nicht, weil ich tatsächlich mit vier Zahlen arbeite (die 3 Zwischensummen und das Endergebnis). Und weil die einzelnen Blöcke auch immer wieder auf die letzte Stelle gekürzt werden, würde bei mir das Ergebnis sogar in ein Byte passen. Ich habe aber auch Integer genommen, um im Fehlerfall mit -1 beenden zu können.


Zum Abschluss: Ich will keinen auf Ideen bringen, aber am ... äh, *hüstel* ... besten finde ich den "Korrigieren"-Button. Falls man eine Ab18-Nummer braucht, aber keine hat und nicht Papis Persi klauen will, kann man sich ja jetzt eine ... Ich weiß nicht, fällt das nicht schon unter die Rubrik "KeyGen", :twisted:


Gruß.
Popov Threadstarter
ontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic starofftopic star
Beiträge: 1655
Erhaltene Danke: 13

WinXP Prof.
Bei Kleinigkeiten D3Pro, bei größeren Sachen D6Pro oder D7
BeitragVerfasst: Do 10.07.03 18:39 
:twisted: :twisted: :twisted: :twisted: :twisted:

Nein ich hatte keine Hintergedanken 8). Aber seinen wir doch mal ehrlich - man gehe auf die Webseite der Bundesdruckerei und holt sich den Beispielausweis der Erika Mustermann. Und die ist auch schon Volljährig.

Aber zurück zum Thema:

Wie gesagt, ist IsLeapYear zwar gut, aber meine Berechnung ist ausreichend. Die allgemeine Bereichnung eines Schaltjahres ist, daß man das Jahr durch vier teilt. Ist der Nachkommawert Null, dann ist es ein Schaltjahr.

Ansonsten weiß ich nicht was für ein Rechner du hast. Bei dir haben alle meine Programme Probleme mit dem Datum (siehe XMasCap). :cry: :cry: :cry:

Zu der Prüfsummenberechnung. Ich hab etliche Codes im Internet gesehen die auch Prüfsummen berechnen. Alle berechnen die Summen für sich. Wenn du mein Code ansiehst, dann wirst du bemerken, das bei mir Zeichenketten belliebiger länge berechnet werden können. Also eine Funktion für alle Berechnungen. Zugegeben, man kann die Zahlen auch anders prüfen, aber jedem das seine. Ist eine andere Art zu prüfen.

_________________
Popov
MathiasSimmack
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 10.07.03 20:21 
Popov hat folgendes geschrieben:
Ansonsten weiß ich nicht was für ein Rechner du hast. Bei dir haben alle meine Programme Probleme mit dem Datum (siehe XMasCap). :cry: :cry: :cry:

Das liegt wohl hauptsächlich an meinem Datumsformat YYYY-MM-TT. Aber das passiert nicht nur bei deinen Programmen. Ich glaube, eins von Onz und eins von AXMD haben mal die gleichen Probleme verursacht. Das ist eben das Problem, wenn man mit einem festgelegten Format arbeitet, während der Anwender durchaus was anderes nutzen kann. Aber egal, hier ließ sich das Problem ja recht einfach lösen.

Ich hab´s mittlerweile auch bei minimalen Änderungen deines Codes (die Betonung liegt auf "minimal"!) hinbekommen, dass dein Programm meine Prüffunktion benutzt. :)