Deutsche Personalausweisnummern verifizieren
Geschrieben von: Christoph Wille Im Internet findet man immer wieder interessante Ansätze, die Identität bzw. das Alter der Surfer zu bestimmen. Einer davon ist die Personalausweisnummer vom Surfer eintippen zu lassen, da diese neben allgemeinen Angaben auch das Alter beinhaltet. Mit Hilfe von in der Personalausweisnummer eingebauten Prüfziffern kann man kontrollieren, ob die Eingaben korrekt sind. Sicherheitshinweis Nicht nur wir können die Prüfziffern verifizieren, sondern die "Gegenseite" kann da der Algorithmus bekannt ist, sich gültige Personalausweisnummern generieren lassen. Ein Beispiel dazu ist auf der Seite Berechnung der Personalausweis-Nummern inklusive Prüziffern zu finden. Wie sieht nun eine Personalausweisnummer aus? Im Newsarchiv von Google findet sich ein Posting, aus dem diese Aufschlüsselung herauskopiert ist: 731731731 731731 731731 ********* ****** ****** wwwwNNNNNaD<<yyMMddb<YYmmDDc<<<<<<d ||||||||||| ||||||| ||||||| | ||||||||||| ||||||| ||||||| -\__ Pruefsumme ALLER Ziffern ||||||||||| ||||||| ||||||| ||||||||||| ||||||| ||||||-\__ Pruefsumme Ablaufdatum ||||||||||| ||||||| ||||--\__ Ablaufdatum Tag ||||||||||| ||||||| ||--\__ Ablaufdatum Monat ||||||||||| ||||||| --\__ Ablaufdatum Jahr ||||||||||| ||||||| ||||||||||| ||||||-\__ Pruefsumme Geb.-Datum ||||||||||| ||||--\__ Geb.-Tag ||||||||||| ||--\__ Geb.-Monat ||||||||||| --\__ Geb.-Jahr ||||||||||| |||||||||| \__ Staatszugehoerigkeit D = Deutsch ? ||||||||| \__ Pruefsumme fuer wwwwNNNNN ||||-----\__ laufende Zaehlnummer ----_ Erstwohnsitz Kennzahl Wie man sieht, gibt es vier Prüfziffern a, b, c und d. Die erste Prüfziffer, a, wird über die Kennzahl des Erstwohnsitzes und eine fortlaufende Ausweisnummer errechnet. Die zweite über das Geburtsdatum, und die dritte über das Ablaufdatum. Die Prüfziffer d ist etwas spezieller: diese wird nach Errechnung von a, b und c über alle Ziffern errechnet (also mit den drei Prüfziffern inkludiert, damit man die Prüfziffern prüfen kann). Details über den Algorithmus finden sich im Posting beziehungsweise sehr detailliert aufgeschlüsselt im Artikel Prüfziffern: Deutscher Personalausweis. Die Kurzform des Algorithmus zur Prüfziffernberechnung: Man nimmt die erste Zahl, und multipliziert sie mit 7. Dazu addiert man die zweite Zahl, die zuvor mit 3 multipliziert wird. Die dritte wird einfach dazuaddiert (mit 1 multipliziert). Hat man mehr als drei Zahlen, beginnt man bei der vierten Zahl wieder mit 7 zu multiplizieren (und so weiter). Von der so errechneten Prüfsumme nimmt man die Einerstelle, und schon ist die Prüfziffer fertig. Wie einfach das ist, wird jeder im Code sehen. Die Klasse PersonalausweisnummerUm die Wiederverwendung in allen Programmiersprachen zu erleichtern, habe ich die Klasse Personalausweisnummer in eine eigene Datei namens PersoClass.cs ausgelagert. Das erlaubt das direkte Einbinden in C# Projekte, beziehungsweise das Kompilieren als eigenständige Assembly, die dann auch in zB VB.NET ASP.NET Projekten eingebunden werden kann. Die Klasse besitzt folgende Eigenschaften und Methoden: public class Personalausweisnummer { public Personalausweisnummer(); public string ErstwohnsitzKennzahl { set; } public string Zaehlnummer { set; } public string Geburtsdatum { set; } public string Ablaufdatum { set; } public bool IsDataValid(); public bool PruefsummenBerechnung(out byte PruefsummeAZiffer, out byte PruefsummeBZiffer, out byte PruefsummeCZiffer, out byte PruefsummeDZiffer); } Die Eigenschaften sind alle nur mit einem set Accessor ausgestattet, das heißt, man kann die Eigenschaften nur setzen, nicht aber lesen. Die Methode IsDataValid wird von der Methode PruefsummenBerechnung aufgerufen, bevor die vier Prüfziffern berechnet werden - damit stelle ich sicher, daß alle vier Eigenschaften korrekt gesetzt wurden. Die EigenschaftenDie vier Properties der Klasse Personalausweisnummer nehmen jeweils einen String als Input an. Diese Strings werden in den set Accessors in die Einzelziffern umgewandelt, und diese in Arrays gespeichert: public class Personalausweisnummer { private int[] abErstwohnsitzKennzahl; private int[] abZaehlnummer; private int[] abGeburtsdatum; private int[] abAblaufdatum; private int ValidData; public Personalausweisnummer() { abErstwohnsitzKennzahl = new int[4]; abZaehlnummer = new int[5]; abGeburtsdatum = new int[6]; abAblaufdatum = new int[6]; ValidData = 0; } Die Arrays sind 4, 5 beziehungsweise zweimal 6 Elemente groß. Die Arrays werden im Konstruktor initialisiert, ebenso wie die Membervariable ValidData, die wir zum Mitführen der Gültigkeit der vier Arrays verwenden. Diese Variable wird jeweils in den set Accessor gesetzt; sehen wir uns den ErstwohnsitzKennzahl Accessor exemplarisch an: public string ErstwohnsitzKennzahl { set { ValidData &= ~((int)Persodaten.ErstwohnsitzKennzahl); if (value.Length != 4) { throw new ArgumentException("Erstwohnsitz Kennzahl muß 4 Ziffern lang sein"); } try { for (int i=0; i <= 3; i++) { abErstwohnsitzKennzahl[i] = Int32.Parse(value[i].ToString()); } } catch(Exception e) { throw e; } ValidData |= ((int)Persodaten.ErstwohnsitzKennzahl); } } Bei Persodaten, die bei der Zuweisung von ValidData verwendet wird, handelt es sich um eine Enumeration: public enum Persodaten { ErstwohnsitzKennzahl = 1, Zaehlnummer = 2, Geburtsdatum = 4, Ablaufdatum = 8 } Damit habe ich den Trick auch schon verraten, wie man die Gültigkeit von vier Variablen in einer einzigen speichert: mit bitweisen Operationen. Am Anfang des Accessors wird die Variable auf ungültig gesetzt (Und-en mit dem Komplementär), und falls kein Fehler aufgetreten ist, wird am Ende des Accessors geodert. Fehlerfälle sind inkorrekte Stringlängen und Nicht-Ziffern in den Strings, auf weitere Überprüfungen habe ich verzichtet. IsDataValid - Kontrolle vor der BerechnungBevor PruefsummenBerechnung mit der Berechnung startet, ruft diese die Methode IsDataValid auf. Und diese vergleicht die Membervariable ValidData mit den geoderten Enumerationmembers (es sind nur dann alle Bits gesetzt, wenn alle Daten korrekt waren): public bool IsDataValid() { int nValidIf = ((int)Persodaten.ErstwohnsitzKennzahl) | ((int)Persodaten.Zaehlnummer) | ((int)Persodaten.Geburtsdatum) | ((int)Persodaten.Ablaufdatum); return (nValidIf == ValidData); } Nach diesem Check kann die Prüfziffernberechnung starten. PrüfziffernberechnungBeginnen wir in der Methode PruefsummenBerechnung ganz oben: public bool PruefsummenBerechnung(out byte PruefsummeAZiffer, out byte PruefsummeBZiffer, out byte PruefsummeCZiffer, out byte PruefsummeDZiffer) { PruefsummeAZiffer = PruefsummeBZiffer = PruefsummeCZiffer = PruefsummeDZiffer = 0; if (!IsDataValid()) return false; Die out Variablen müssen initialisiert werden, damit falls IsDataValid ein false liefert, diese Variablen auf gültige Werte gesetzt sind (uninitialisierte out Variablen dürfen niemals die Methode verlassen). Nach diesem ersten (und einzigen) Check wird auch schon die Prüfziffer a berechnet: int PruefsummeA; PruefsummeA = (abErstwohnsitzKennzahl[0] * 7) + (abErstwohnsitzKennzahl[1] * 3) + (abErstwohnsitzKennzahl[2]* 1) + (abErstwohnsitzKennzahl[3] * 7) + (abZaehlnummer[0] * 3) + (abZaehlnummer[1] * 1) + (abZaehlnummer[2] * 7) + (abZaehlnummer[3] * 3) + (abZaehlnummer[4] * 1); string strPruefsummeA = Convert.ToString(PruefsummeA); PruefsummeAZiffer = Convert.ToByte(strPruefsummeA.Substring(strPruefsummeA.Length - 1)); Hier sieht man den Algorithmus bei der Arbeit, und er ist tatsächlich nicht schwer zu verstehen. Die letzten beiden Zeilen erledigen das Ermitteln der Einerstelle - diese wird dann auf die erste out Variable zugewiesen. Die Berechnung für b und c läuft ident, interessant ist wieder d, damit man sieht, wie die anderen Prüfziffern in die Berechnung einfliessen: int PruefsummeD; PruefsummeD = (abErstwohnsitzKennzahl[0] * 7) + (abErstwohnsitzKennzahl[1] * 3) + (abErstwohnsitzKennzahl[2]* 1) + (abErstwohnsitzKennzahl[3] * 7) + (abZaehlnummer[0] * 3) + (abZaehlnummer[1] * 1) + (abZaehlnummer[2] * 7) + (abZaehlnummer[3] * 3) + (abZaehlnummer[4] * 1) + (PruefsummeAZiffer * 7) + (abGeburtsdatum[0] * 3) + (abGeburtsdatum[1] * 1) + (abGeburtsdatum[2] * 7) + (abGeburtsdatum[3] * 3) + (abGeburtsdatum[4] * 1) + (abGeburtsdatum[5] * 7) + (PruefsummeBZiffer * 3) + (abAblaufdatum[0] * 1) + (abAblaufdatum[1] * 7) + (abAblaufdatum[2] * 3) + (abAblaufdatum[3] * 1) + (abAblaufdatum[4] * 7) + (abAblaufdatum[5] * 3) + (PruefsummeCZiffer * 1); string strPruefsummeD = Convert.ToString(PruefsummeD); PruefsummeDZiffer = Convert.ToByte(strPruefsummeD.Substring(strPruefsummeD.Length - 1)); Der Algorithmus wird einfach auf alle Zahlen in ihrer Reihenfolge angewendet. Und damit haben wir alle vier Prüfziffern, und die Methode beendet mit true. Verwendung der Klasse PersonalausweisnummerIm Download mit dabei ist eine kleine Kommandozeilenanwendung, die die Verwendung anhand eines Datensatzes demonstriert: class MainClass { public static void Main(string[] args) { Personalausweisnummer perso = new Personalausweisnummer(); try { perso.ErstwohnsitzKennzahl = "1000"; // vierstellig perso.Zaehlnummer = "10000"; // fünfstellig perso.Geburtsdatum = "730729"; // Jahr, Monat, Tag perso.Ablaufdatum = "050101"; // Jahr, Monat Tag } catch(Exception e) { Console.WriteLine("Daten inkorrekt: "); Console.WriteLine(e.Message); } byte a, b, c, d; bool bOk = perso.PruefsummenBerechnung(out a, out b, out c, out d); if (bOk) { Console.WriteLine("a: {0} b: {1} c: {2} d: {3}",a, b, c, d); } else { Console.WriteLine("Berechnung der Prüfsummen konnte nicht durchgeführt werden."); } } } Bei den vier Eigenschaften können Exceptions auftreten, daher ist der Zuweisungsblock in try...catch eingebettet. Danach wird die Methode PruefsummenBerechnung aufgerufen, und die Resultate an die Console ausgegeben. Wer die Klasse in ASP.NET oder anderen Programmiersprachen als C# verwenden will, kann die Batch-Datei builddll.bat aufrufen - damit erhält man eine Assembly, die beliebig weiterverwendet werden kann. SchlußbemerkungFalls man die Personalausweisnummer zur Verifizierung des Alters einsetzt, sollte man sich immer bewußt sein, daß jeder eine "gültige" Nummer errechnen kann. Fälschungssicher - ohne die physische Karte in Händen zu halten - ist die Personalausweisnummer nicht. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
Datentypen in C# Links zu anderen Sites
#develop Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |