Online-Voting
Seit einiger Zeit mache ich mir schon Gedanken um eine technische Umsetzung einer freien und geheimen Wahl, die alle Anforderungen an Transparenz, Anonymität und Sicherheit erfüllt.
Ich habe mich inzwischen diesbezüglich ein bisschen Schlau gemacht. Ein wirklich sichere und ausgereiftes System hat doch eine gehörige Komplexität. Ich möchte hier trotzdem die Behauptung wagen, dass ich eine Lösung gefunden habe, die meiner Meinung nach, alle Anforderungen erfüllt. Im folgenden möchte ich dies System beschreiben und zur Diskussion stellen.
Anforderungen
Die Anforderungen an ein solches System lassen sich aus unserem allgemeinen Wahlrecht ableiten. Das Bundesamt für Sicherheit in der Informationstechnik(BSI) hat in [1] diese Anforderungen wie folgt formuliert:
- Allgemeine Wahl: Jeder Wahlberechtigte muss wählen können.
- Unmittelbare Wahl: Jedes abgegebene Votum wirkt sich unmittelbar auf das zu wählende Gremium aus.
- Freie Wahl: Es darf keinen Druck auf die Entscheidung vor oder während der Wahl und keinen Nachteil durch die Entscheidung nach der Wahl geben.
- Gleiche Wahl: Jedes gültige abgegebene Votum hat den gleichen Wert.
- Geheime Wahl: Die Entscheidung des Wählers darf nie auf ihn zurückgeführt werden können.
Jede einzelne Anforderung klingt erstmal simpel - bei einem Online System haben diese Anforderungen es aber auch in sich.
Zusätzlich, zu den ober genannten Anforderungen, müsste das gesuchte System auch namentliche Abstimmungen unterstützen. Wir werden später sehen, dass dies nicht so trivial ist, wie es klingt. Es ist wichtig, hierdurch nicht die Anonymisierung des Wählers zu kompromittieren. Aber der Reihe nach...
Im Nachfolgenden kommt jetzt sehr viel Crypto-Foo. Ich befürchte, dass diesen Teil kaum jemand lesen möchte. Im Abschnitt über die Anwendung des System, wird es dann wieder etwas einfacher. Wer kein Interesse am Crypto-Foo hat, möge mir doch zumindest ein Feedback bezüglich der Akzeptanz der Anwendungsschnittstelle geben.
Allgemeine Wahl
Diese Allgemeinheit beschränkt sich in unserem Fall auf Mitglieder der Piratenpartei und unter Umständen sogar auf Mitglieder eines einzelnen Landesverbandes(LV). Es wird also eine sichere Methoden gesucht, die die Mitgliedschaft in der Partei oder einem LV überprüfen kann. Hierbei sollte unbedingt vermieden werden, die Mitgliedsliste heranzuziehen. Für die eigentliche Mitgliederverwaltung ist eine Mitgliederliste natürlich notwendig - in Online-Systeme sollte eine solche Liste jedoch nicht vorgehalten werden. Für alle Systeme muss der Grundsatz der Datensparsamkeit gelten. (Die Überprüfung der Mitgliedschaft kann zur Anwesenheits- und Zutrittskontrolle für LV- und Bundesparteitagen nützlich sein. Es bietet sich also an, diese Überprüfung als Dienst für verschiedene Anwendungsfälle zu implementieren)
Wenn das Vorhandensein und der Besitz eines Mitgliedsausweis als hinreichendes Kriterium für die Mitgliedschaft gewertet werden kann, kann dies leicht anhand der Mitgliedsnummer und einem Card Verification Code(CVC) geprüft werden. Dies verfahren wird auch von Kreditkarten benutzt. Hierbei wird die Kreditkartennummer und der umseitig aufgedruckte CVC abgefragt. Damit hiermit eine Aussage über die Mitgliedschaft getroffen werden kann, muss dem befragten Dienst keine Mitgliedsliste vorliegen, sofern es einen mathematischen Zusammenhang zwischen diesen Zahlen gibt. Dieser mathematische Zusammenhang darf allerdings nur der Ausgabestelle und dem überprüfenden Dienst bekannt sein.
Wir haben hier also schon mit mindestens zwei Akteuren zu tun, und wir werden auch noch auf einige Andere stoßen. Ich möchte daher an dieser Stelle einige Abkürzungen einführen, um die nachfolgende technische Beschreibungen etwas zu vereinfachen.
M# = Mitgliednummer - Eindeutige Nummer des Mitglieds, die sich aus einer Kennzahl für den LV und einer laufenden Nummer zusammensetzen sollte.
CVC = Card Verifikation Code - Dieser Code wird mittels einer Hash Funktion aus M# und M_s berechnet.
M = Mitgliedsverwaltung - Die kann und sollte ein Offline System sein. Hier werden Mitgliedslisten mit Name und Anschrift des Mitglieds geführt. Diese Stelle vergibt auch die Mitgliedsnummer M#.
M_s = Dies ist ein Geheimnis(Secret), dass von M erzeugt wurde und zur Generierung der CVC benötigt wird. Dies Geheimnis kann mit jedem Ausgabezyklus der Mitgliedsausweise neu erzeugt werden. Dies Geheimnis wird ausschließlich an den Authentifizierungsdienst A weitergegeben.
A = Dies ist der Authentifizierungsdienst. Er kennt nur das Geheimnis M_s, dass ihm von der Mitgliederverwaltung mitgeteilt wird. Wenn man diesem Dienst eine M# und einen CVC nennt, kann er anhand dieser Daten prüfen, ob es sich um einen gültigen Mitgliedsausweis handelt.
A_Reg = Ist ein Register, dass für Dauer einer Wahl von A geführt wird. In dieser Register wird jede für gültig befunden Mitgliedsnummer einmalig eingetragen.
E# = Nummer der laufenden Abstimmung(election)
A_pk = Der öffentliche(public) RSA Key des Authentifizierungsdienstes.
A_sk = Der geheime(secret) RSA Key des Authentifizierungsdienstes.
U = Wahlurnen Server - Hier können anonymisierte oder namentliche Wahlzettel eingeworfen werden. Dieser Server ist auch für die öffentliche Auszählung der Stimmen zuständig.
U_pk = Der Der öffentliche(public) RSA Key des Wahlurnen Servers.
U_sk = Der geheime(secret) RSA Key des Wahlurnen Servers.
Wahlverfahren
Das hier beschrieben Wahlverfahren entstammt einer Anregung von Prof. Otten in [2]. Es enthält die für jede Wahl typischen Vorgänge Wählerregistrierung, geheime Wahl und öffentliche Auszählung. Es wurde zusätzlich um die Möglichkeit einer namentlichen Abstimmung ergänzt.
Ausweiserstellung durch die Mitgliedsverwaltung
Die Vorderseite des Ausweis enthält den Namen, die Anschrift, und die Mitgliedsnummer M#. Auf einem abtrennbaren Teil des Ausweises oder auf seiner Rückseite befindet sich der CVC.
Vorderseite
Max Mustermann Hafenplatz 5 10963 Berlin
11 000 012 567 (eventuell Gültig bis 07/10)
Rückseite
CVC 10 23 40 22
Ein abtrennbarer Teil hätte den Vorteil, dass man M# und CVC getrennt aufbewahren kann.
Der CVC wird gebildet, indem man M# und M_s konkateniert und eine Hash-Funktion hierauf anwendet. Der Aufwand für die Ausgabestelle ist also denkbar gering.
Prüfen, ob Ausweis gültig ist
Der Dienst A erhält von M für jenen Ausgabezyklus von Ausweisen das Geheimnis M_s (Der übliche Intervall hierfür kann ein bis zwei Jahre betragen).
Um die Gültigkeit eines Ausweises zu Prüfen, nennt man A die Mitgliedsnummer M# und CVC. Kann mittels M# und M_s der Wert von CVC errechnet werden, dann ist der Ausweis gültig. Dies ist die einfachste Form der Überprüfung. Für anonyme Wahl reicht das jedoch nicht aus. Hier drauf gehe später noch ausführlicher ein.
Stimmabgabe
Ein leerer Stimmzettel wird von U bezogen. Dieser Stimmzettel wird vom Wähler ausgefüllt und gegen Korrelationsangriffe mit zufälligen Füllbits versehen. Diese Füllbits werden auch als 'salt' bezeichnet, da hiermit die Nachricht quasi gesalzen wird. Diese Füllbits lassen sich leicht durch Benutzerinteraktion erzeugen. Er kann hierfür zum Beispiel die Bewegungen der Maus herangezogen werden.
Der 'gesalzene' Stimmzettel wird vom Wähler mit U_pk verschlüsselt. A erhält vom Wähler nun diesen verschlüsselten Stimmzettel, den A nicht entschlüsseln kann. Zusätzlich wird M# und CVC übertragen. Da A das Geheimnis M_s kennt, kann A nun also wieder den Hash von M# und M_s berechnen. Wenn das Ergebnis mit CVC übereinstimmt, dann signiert A den verschlüsselten Wahlzettel blind mit seinem geheimen Key A_sk. Die Signatur wird als Antwort an den Wähler geschickt.
Der Wähler hat nun also einen verschlüsselte anonymen Stimmzettel, dessen Echtheit durch die Signatur von A bestätigt wird. Den Stimmzettel und die Signatur muss er nun also nur noch an den Wahlurnen Server senden. Diese überprüft die Signatur von A mit Hilfe von A_pk und legt den verschlüsselten Stimmzettel in die Urne.
Auszählung
Nach Ende der Wahl wird der geheime Key U_sk am Wahlurnen Server eingegeben. Erst jetzt kann er die Stimmzettel öffnen und zählen. Sowohl die verschlüsselten als auch die entschlüsselten Stimmzettel können jetzt offen gelegt werden. Jeder Wähler hat die Möglichkeit seinen Stimmzettel anhand des Fingerprint wiederzufinden - kann also prüfen, ob seine Stimme gezählt wurde.
zusätzliche Sicherungen
- Replay Attacke
Replay Attacken können leicht durch die Einführung eines Wählerregisters auf A verhindert werden. Hierfür ist es sinnvoll die Abstimmungsnummer E# einzuführen, damit mehrere Abstimmungen parallel möglich sind. Die Eintragung in das Register A_Reg ist jeweils nur einmal möglich. Weitere Authentifizierungsversuche werden abgelehnt.
- Vertrauen in die Betreiber von A und U
Die Stimmzettel können leicht mit mehr als einem U_pk verschlüsselt werden. Die Ersteller der Schlüsselpaar U_sk/U_pk können bei jeder Wahl wechseln. Da U_sk erst nach der Wahl eingegeben wird, kann somit ein N*2 Augenprinzip eingeführt werden. Das gleiche gilt für das Schlüsselpaar A_sk/A_pk. Auch A_pk muss erst nach Ende der Wahl zur Verfügung stehen. Es könne hier auch N Signaturen gefordert sein.
- Man in the Middle
'Man in the Middle' Attacken können durch gültige ssl Zertifikate von A und U verhindert werden.
Anwendung
Der Wähler muss zum Glück die oben beschriebenen Aktionen nicht wirklich selber ausführen. Ein vollständige Implementierung der Wählersoftware in Javascript ist denkbar. Er muss dann nur noch nach dem Aufruf der Webseite für die entsprechende Wahl folgende Schritte durchführen:
- Mitgliedsnummer und CVC eingeben.
- 'salt' erzeugen, durch einige willkürliche Bewegungen der Maus
- Stimmzettel ausfüllen
- eventuell Fingerprint des Stimmzettels aufschreiben um die Stimmabgabe nach der Wahl zu verifizieren.
Er braucht für das Verfahren keine eigenen RSA Keys!
Ich habe einen Entwurf für ein Webfrontend für das Voting System erstellt. Man kann sehen, dass sich das Webformular in drei Bereiche aufteilt. Teil eins und zwei werden an den Authentifizierungsdienst A gesendet, Der dritte Teil wird dann beim Urnenserver abgegeben.
namentliche Abstimmung
Für die namentliche Abstimmung wäre ein zweiter CVC und ein zweites M_s notwendig, dass Name und Anschrift mit einschließt. Um A nicht zu kompromittieren, wird in diesem Fall der Stimmzettel direkt an U gesendet, da eine Anonymisierung ja nicht notwendig ist. U kann dann zusätzlich noch M# und CVC bei A überprüfen.
[1] Markus Ullmann, Frank Koob, Harald Kelter, Anonyme Online-Wahlen, Lösungsansätze für die Realisierung von Online-Wahlen, DuD • Datenschutz und Datensicherheit 22 (1998) V2.6
[2] Dieter Otten, Hash mich, ich bin der Wähler! 23.09.2005, http://www.sueddeutsche.de/computer/910/321779/text/