Wahlprotokoll#

Das Wahlprotokoll ist in drei Phasen gegliedert: die Registrierungs-, die Anmelde- und die Abstimmungsphase. Die Registrierung ist pro Teilnehmer nur einmal erforderlich; die Anmeldephase wird einmal pro Veranstaltung durchgeführt, die Abstimmungsphase unter Umständen mehrmals pro Veranstaltung.

Registrierung#

Bei einer Registrierung wird für ein bestimmtes Mitglied der Gemeinschaft eine offene Identität auf einem Schlüsselserver erstellt. Dieser Schritt ist für das Durchführen von Abstimmungen nicht zwingend erforderlich, da Teilnehmer an einer Abstimmung hierfür ohnehin mit einer temporären, anonymen Identität ausgestattet werden. Das dafür erforderliche Zustellen von Losnummern wird allerdings erleichtert, wenn die Teilnehmer über eine offene Identität verfügen (siehe weiter unten den Abschnitt „Übermittlung der Losnummern“ in „Vorbereitung einer Veranstaltung“).

Die Registrierung besteht aus zwei Schritten: dem Vergeben einer Teilnehmerkennung und dem Hinterlegen eines öffentlichen Schlüssels.

Teilnehmerkennung vergeben#

Das Vergeben der Teilnehmerkennung geschieht durch einen Administrator, der die Mitgliederliste einsehen kann und auf dem Schlüsselserver über die Berechtigung verfügt, neue Identitäten anzulegen. Dabei kann es sich um einen Menschen handeln oder um ein Computerprogramm, das auf einem zentralen Rechner läuft und ein maschinelles Authentifizierungsverfahren nutzt. In beiden Fällen muss es eine Regel geben, die festlegt, wie aus einem bestimmten Mitgliederdatensatz eine Teilnehmerkennung gebildet wird. Und diese Regel muss so gewählt sein, dass zu einem Datensatz stets dieselbe Kennung gebildet wird, auch wenn sich bestimmte Mitgliedsdaten zwischenzeitlich geändert haben. Es muss sichergestellt sein, dass ein Mitglied zu keinem Zeitpunkt mehr als eine Identität erhalten kann.

Wenn der Administrator eine Registrierung startet, erzeugt er nach dem Zufallsprinzip einen Berechtigungscode und hinterlegt dessen SHA256-Hash zusammen mit der Teilnehmerkennung auf dem Schlüsselserver. Teilnehmerkennung und Berechtigungscode werden an das betreffende Mitglied übermittelt, wobei durch die Art der Übermittlung und der vorgeschalteten Prüfung sichergestellt sein muss, dass diese Daten tatsächlich an das richtige Mitglied gelangen. Dies kann zum Beispiel durch einen Versand per Post an die im Mitgliederdatensatz hinterlegte Anschrift oder einen digitalen Versand an die E-Mail-Adresse des Mitglieds geschehen.

Öffentlichen Schlüssel hinterlegen#

Nachdem das Mitglied seine Teilnehmerkennung und seinen Berechtigungscode erhalten hat, sendet es seinen öffentlichen Schlüssel zusammen mit Kennung und Code an den Schlüsselserver. Der überprüft, ob der Hash des übermittelten Berechtigungscodes mit dem Hash übereinstimmt, der für die betreffende Teilnehmerkennung hinterlegt ist, und speichert dann den Schlüssel zu der Teilnehmerkennung ab. Der Berechtigungscode verliert damit seine Gültigkeit.

Sollte irgendwann die Notwendigkeit bestehen, einen neuen öffentlichen Schlüssel zu hinterlegen, zum Beispiel weil der alte kompromittiert wurde oder der zugehörige private Schlüssel verlorengegangen ist, muss das Mitglied beim Administrator einen neuen Berechtigungscode anfordern. Bei der Zusendung ist wiederum sicherzustellen, dass der Code tatsächlich an das richtige Mitglied gelangt.

@startuml

title Registrierung eines neuen Mitglieds
actor "Mitglied" as MB
database "Schlüsselserver" as KS
participant "Administrator,\nOIDC-Client o. ä." as ADM
database "Mitglieder-DB" as MDB

MB-->ADM: Registrierungsanforderung
activate ADM
ADM<-->MB:Authentifzierung
ADM<-->MDB:Anforderung\nMitgliedsdatensatz
note left of ADM:Teilnehmerkennung ermitteln\noder neu erzeugen
ADM-->MDB: ggf. Teilnehmerkennung\nhinterlegen
ADM->KS:**participant-details-request**\n(Teilnehmerkennung)
activate KS
KS->ADM: **participant-details**
deactivate KS
note left of ADM:Berechtigungscode erzeugen
ADM->KS:**registration**\n(Teilnehmerkennung, SHA256-Hash\ndes Berechtigungscodes)
activate KS
note left of KS:Absenderberechtigung prüfen
note left of KS:Hash des Berechtigungscodes bei\nTeilnehmerkennung hinterlegen
KS->ADM:**registration-confirmation**
deactivate KS
ADM-->>(3)MB:Registrierungsinformation per E-Mail, Briefpost, HTTP-Response o. ä.\n(Teilnehmerkennung, Berechtigungscode)
deactivate ADM
activate MB
note right of MB: Schlüsselpaar erzeugen
MB->KS:**key-submission**\n(Teilnehmerkennung, Berechtigungscode,\nöffentl. Schlüssel)
activate KS
note right of KS:öffentlichen Schlüssel für\nTeilnehmerkennung hinterlegen,\nBerechtigungscode ungültig\nmachen
KS->MB:**key-submission-confirmation**
deactivate KS
note right of MB:Schlüssel als hinterlegt kennzeichnen
deactivate MB

@enduml

Message-Type: registration
From: admin01@partcp.example.org
To: partcp.example.org
Participant-Id: p003283
Credential: 6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
Message-Type: registration-confirmation
From: partcp.example.org
To: admin01@partcp.example.org
Original-Message: |
  ...
Participant-Data:
  id: p003283
  credential: 6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090
Message-Type: key-submission
From: p003283@partcp.example.org
To: partcp.example.org
Credential~: "lFpidrMI5KMrFP7Vnb02Uw==:wZHfct/V"
Public-Key: lqLGtV1EtR8ClvIPAYyiWeeU3Ug9t9agY1jyjZWJxe6XPB3rnpZTKB67gctR4n4p...
Message-Type: key-submission-confirmation
From: partcp.example.org
To: p003283@partcp.example.org
Original-Message: |
  ...
Participant-Data:
  id: p003283
  public_key: lqLGtV1EtR8ClvIPAYyiWeeU3Ug9t9agY1jyjZWJxe6XPB3rnpZikjTKB67IgXd...

Vorbereitung einer Veranstaltung#

Um eine oder mehrere Abstimmungen durchzuführen, muss zunächst eine Veranstaltung definiert und der Teilnehmerkreis festgelegt werden. Außerdem müssen anonyme Identitäten erstellt und unter den Teilnehmer „verlost“ werden. Die Schritte im Einzelnen:

  1. Der Veranstaltungsleiter legt Titel und Beschreibung der Veranstaltung fest und teilt dem Abstimmungsserver mit, wie viele Mitglieder stimmberechtigt sind.

  2. Der Abstimmungsserver erzeugt die gewünschte Anzahl an Teilnehmerkennungen mit Berechtigungscodes und speichert diese verschlüsselt auf der Festplatte. Zu jeder Teilnehmerkennung wird nach dem Zufallsprinzip eine Losnummer erzeugt, deren SHA256-Hash ebenfalls auf dem Server gespeichert wird und als Index für den Zugriff auf Teilnehmerkennung und Berechtigungscode dient. Die erzeugten Losnummern werden in zufälliger Reihenfolge an den Veranstaltungsleiter zurückgeliefert.

  3. Der Veranstaltungsleiter teilt jedem stimmberechtigten Mitglied eine Losnummer zu und sorgt dafür, dass sie dem betreffenden Mitglied – und nur diesem – zugesendet bzw. bereitgestellt wird. Wie dieser Schritt praktisch ausgestaltet werden kann, ist unten im Abschnitt „Übermittlung der Losnummern“ beschrieben. Sollten Losnummern übrig bleiben, werden diese vom Veranstaltungsleiter an den Abstimmungsserver übermittelt und für ungültig erklärt.

  4. Der Veranstaltungsleiter erklärt die Anmeldephase für eröffnet (oder der vordefinierte Zeitpunkt des Anmeldestarts ist erreicht).

  5. Der Abstimmungsserver blockiert den öffentlichen Lesezugriff auf das Verzeichnis, in dem die Veranstaltungsdaten gespeichert sind.

  6. Das einzelne Mitglied ruft mit Hilfe seines Clients die Teilnehmerkennung und den Berechtigungscode ab, die auf dem Abstimmungsserver mit seiner Losnummer verknüpft sind. Falls mit der betreffenden Losnummer bereits zuvor ein Abruf erfolgte, wird die Anfrage zurückgewiesen. Abrufe werden ohne Zeitstempel protokolliert.

  7. Der Client erzeugt ein Schlüsselpaar und überträgt den öffentlichen Schlüssel zusammen mit Teilnehmerkennung und Berechtigungscode zum Abstimmungsserver. Der Server prüft, ob der Hash des Berechtigungscodes mit dem gespeicherten Hash übereinstimmt und hinterlegt den öffentlichen Schlüssel dauerhaft für die betreffende Teilnehmerkennung. Der Berechtigungscode verliert damit seine Gültigkeit und ist nicht erneut verwendbar.

  8. Der Veranstaltungsleiter erklärt die Anmeldephase für beendet (oder der vordefinierte Zeitpunkt des Anmeldeendes ist erreicht).

  9. Der Abstimmungsserver gibt den öffentlichen Lesezugriff auf das Veranstaltungsverzeichnis wieder frei. Losnummerneinreichungen und Schlüsselhinterlegungen werden nun nicht mehr akzeptiert.

@startuml

title Vorbereitung einer Veranstaltung/Abstimmung
actor "Mitglied" as MB
database "Abstimmungsserver" as VS
participant "Versammlungs-\nleiter" as ADM

activate ADM
ADM->VS:**event-definition**\n(Startdatum, Name, Beschreibung)
activate VS
VS->ADM:**event-definition-confirmation**\n(Kennung der Veranstaltung)
deactivate VS
note left of ADM:Anzahl der stimmberechtigten\nMitglieder ermitteln
ADM->VS:**multi-registration**\n(Veranstaltungskennung, Anzahl)
activate VS
note left of VS:Teilnehmerkennungen, Berechtigungs-\ncodes und Losnummern erzeugen
VS->ADM:**multi-registration-confirmation**\n(Losnummern)
deactivate VS
ADM-->>(3)MB:Einladung per E-Mail, Briefpost o. ä.\n(Losnummer)
deactivate ADM
activate MB
==Start Anmeldephase==
|||
activate MB #cccccc
note right of MB:temporäres Schlüsselpaar erzeugen
MB->VS:**lot-request**\n(Losnummer)
activate VS
note right of VS:prüfen, ob Losnummer gültig ist \nund noch nicht abgerufen wurde
VS->MB:**lot** (Teilnehmerkennung,\nBerechtigungscode)
deactivate VS
|||
note right of MB:Schlüsselpaar für veranstaltungs-\nbezogene Teilnehmerkennung erzeugen
MB->VS:**key-submission**\n(Teilnehmerkennung, Berechtigungscode\nöffentlicher Schlüssel)
activate VS
note right of VS:öffentlichen Schlüssel für Teilnehmerkennung\nhinterlegen, Berechtigungscode ungültig machen
VS->MB:**key-submission-confirmation**
deactivate MB
deactivate VS
==Ende Anmeldephase==
|||
deactivate MB

@enduml

Message-Type: event-definition
From: admin@partcp.example.org
To: partcp.example.org
Event-Data:
  name: Bundesparteitag 2021
  date: 2021-11-27
  estimated_turnout: 10000
Message-Type: multi-registration
From: admin@partcp.example.org
To: partcp.example.org
Event-Id: 20211127-bundesparteitag-2021
Count: 7352
Message-Type: multi-registration-confirmation
From: partcp.example.org
To: admin@partcp.example.org
Original-Message: |
  ...
Lot-Codes~: >
  ntdXUPtFL3zWLJC7xFgfTw==:+g3cmDFlyNb1J50ANXoRo4XoJwAQ+0ShfYkjzm7cHnHSb/CdOFjyHAwCom...
Message-Type: lot-request
To: partcp.example.org
Event-Id: 20211127-bundesparteitag-2021
Lot-Code~: g3cmDFlyNb1J50ANXoR==:o4XoJwAQ+0ShfYkjzm7cHnHSb
Public-Key: qq/oN0xeBIluop53ezk47h3ax66ZGZHVckXK6hQ2zFQu6UDsurz7N5pfmFHoEwaICM1XfcDzN...
Message-Type: lot
From: partcp.example.org
Original-Message: |
  ...
Lot-Content~: >
  0ShfYkjzm7cHnHSbzUsa==:+b1J50ANXoRo4XoJwAQ+0ShfYkjzm7cHnHSb/CdOg3cmDFlyNFjyHAwCom...

Erzeugung der Losnummern#

Eine Losnummer wird durch eine zufällige Auswahl von Buchstaben und Ziffern gebildet. Standardmäßig hat sie eine Länge von 16 Zeichen und besteht aus den Ziffern 1 bis 9 und den Großbuchstaben des lateinischen Alphabets, mit Ausnahme von „I“ und „O“. Die Ziffer 0 sowie die Buchstaben I und O bleiben unberücksichtigt, weil diese beim Lesen leicht verwechselt werden und daher zu Fehlern bei einer manuellen Übernahme in den Client führen können.

Nach diesen Standardvorgaben lassen sich 3316 oder 1,978 * 1024 verschiedene Losnummern bilden, so dass bei einer Veranstaltung mit einer Million Teilnehmern die Wahrscheinlichkeit, eine Nummer zu erraten, bei über 1 : 1018 liegt. Um bei kleineren Veranstaltungen mit kürzeren Losnummern arbeiten zu können, hat der Veranstaltungsleiter die Möglichkeit, eigene Vorgaben für die Nummernerzeugung festzulegen. Er kann die Gesamtlänge der Nummer und die zur Auswahl stehenden Zeichen vorgeben und, falls gewünscht, die Anzahl an Prüfziffern, die mit eingebunden werden sollen. Außerdem ist es möglich, ein Trennzeichen festzulegen, das nach einer bestimmten Anzahl von Zeichen in die Losnummer eingefügt wird, um die Lesbarkeit zu verbessern.

Übermittlung der Losnummern#

Schritt 3 der Anmeldephase sieht vor, dass jedes stimmberechtigte Mitglied eine Losnummer zugeteilt und übermittelt bekommt. Wie dies geschieht, ist für das Wahlprotokoll unerheblich, solange sichergestellt ist, dass a) jedes stimmberechtigte Mitglied eine Losnummer erhält, b) kein nicht-stimmberechtigtes Mitglied eine Losnummer erhält und c) kein stimmberechtigtes Mitglied mehr als eine Losnummer erhält. Im Folgenden sollen verschiedene Wege vorgestellt werden, wie sich dies umsetzen lässt.

Ein einfacher Weg, der jedoch nur bei Präsenzveranstaltungen umsetzbar ist, besteht darin, die Losnummern auf Zettel zu drucken und jedes Mitglied nach Feststellung seiner Stimmberechtigung einen Zettel ziehen zu lassen. Mit einem zusätzlich aufgedruckten QR-Code kann die Übernahme der Losnummer in den Client erleichtert werden. Bei dieser Vorgehensweise müssen die Personen, die am Empfangstresen arbeiten, strikt darauf achten, dass jedes Mitglied tatsächlich nur ein Los zieht. Nach Abschluss der Teilnehmerregistrierung werden die übriggebliebenen Lose gezählt. Aus dieser Zahl wird die Zahl der ausgegebenen Lose ermittelt, und es wird geprüft, ob diese Zahl mit den auf der Teilnehmerliste als anwesend gekennzeichneten Mitgliedern übereinstimmt. Die übriggebliebenen Lose werden anschließend auf dem Abstimmungsserver für ungültig erklärt und vernichtet.

Bei Online-Veranstaltungen ist ein ähnlicher Weg gangbar, nur genügt es dann nicht, die Losnummern auf einfache Zettel zu drucken. Die Gefahr wäre zu groß, dass beim Eintüten und Versenden der Zettel Unbefugte Kenntnis der Losnummern erhalten. Daher ist in diesem Fall der Einsatz spezieller Sicherheitsdrucker erforderlich, bei denen die Losnummer durch eine abrubbelbare Schicht verdeckt oder im Innern eines fest verschlossenen Umschlags gedruckt wird. Dies erhöht die Sicherheit, aber auch den Kosten- und Zeitaufwand.

Ein dritter Weg, der sich für Präsenz- und Online-Veranstaltungen gleichermaßen eignet und der ebenso kostengünstig wie sicher ist, besteht darin, die Abstimmungsplattform selbst für die Übermittlung der Losnummern zu nutzen. Dies setzt voraus, dass sich alle Mitglieder zuvor auf der Plattform mit einer offenen Identität registriert haben (siehe oben den Abschnitt „Registrierung“). In diesem Fall kann der Veranstaltungsleiter für jedes stimmberechtigte Mitglied eine Losnummer mit dessen öffentlichem Schlüssel verschlüsseln und auf dem Abstimmungsserver hinterlegen. Der Client ruft die Losnummer ab und entschüsselt sie mit Hilfe des geheimen Schlüssels. Sie kann dann vom Client sofort für den Abruf der Teilnehmerdaten verwendet werden, ohne dass eine Nummer eingetippt oder ein Code gescannt werden muss.

Durchführen einer Abstimmung#

Dies sind die Schritte, um im Rahmen einer Veranstaltung eine Abstimmung durchzuführen:

  1. Der Veranstaltungsleiter übermittelt die Abstimmungsdetails einschließlich dem Musterstimmzettel an den Abstimmungsserver.

  2. Der Veranstaltungsleiter erklärt die Abstimmung für eröffnet (oder der vordefinierte Startzeitpunkt wird erreicht).

  3. Der Abstimmungsserver blockiert den öffentlichen Lesezugriff auf das Verzeichnis, in dem die Abstimmungsdaten gespeichert sind.

  4. Das einzelne Mitglied ruft über seinen Client den Musterstimmzettel vom Abstimmungsserver ab und füllt ihn aus.

  5. Der Client trägt die anonyme Teilnehmerkennung ein, siginiert das Ganze mit dem zugehörigen privaten Schlüssel und überträgt alles zum Abstimmungsserver.

  6. Der Abstimmungsserver prüft, ob der Stimmzettel eine zugelassene Teilnehmerkennung trägt, ob die Signatur mit dem zu dieser Kennung hinterlegten öffentlichen Schlüssel verifiziert werden kann, ob der Stimmzettel vom Aufbau her dem hinterlegten Muster entspricht und ob alle Pflichtangaben vorhanden sind. Falls die Prüfung fehlschlägt, wird der Stimmzettel zurückgewiesen.

  7. Der Abstimmungsserver speichert den Stimmzettel unter der betreffenden Teilnehmerkennung mit fortlaufender Nummer, aber ohne Zeitstempel, unverschlüsselt ab.

  8. Der Veranstaltungsleiter erklärt die Abstimmung für beendet (oder der vordefinierte Endzeitpunkt wird erreicht).

  9. Der Abstimmungsserver gibt den öffentlichen Lesezugriff auf das Abstimmungsverzeichnis wieder frei. Stimmzettel werden nun nicht mehr angenommen

  10. Der Abstimmungsserver geht Teilnehmer für Teilnehmer durch, wertet jeweils den Stimmzettel mit der höchsten fortlaufenden Nummer aus und übernimmt die Bewertungen ins Gesamtergebnis. Das Gesamtergebnis wird bei den übrigen Abstimmungsdaten gespeichert.

@startuml

title Durchführung einer Abstimmung
actor "Mitglied" as MB
database "Abstimmungsserver" as VS
participant "Versammlungs-\nleiter" as ADM

activate ADM
ADM->VS:**voting-definition**\n(Kennung, Titel, Beschreibung,\nStimmzettel)
activate VS
VS->ADM:**voting-definition-confirmation**
deactivate VS
ADM-->>(3)MB:Teilnehmer benachrichtigen
deactivate ADM
activate MB
==Start Abstimmungsphase==
|||
activate MB #dddddd
MB->VS:**voting-details-request**\n(Abstimmungskennung)
activate VS
VS->MB:**voting-details**\n(Stimmzettel)
deactivate VS
note right of MB: Stimmzettel ausfüllen
|||
MB->VS:**ballot**\n(ausgefüllter Stimmzettel)
activate VS
note right of VS:prüfen, ob Teilnahmeberechtigung\nvorliegt und Stimmzettel vollständig \nund korrekt ausgefüllt wurde
note right of VS:Stimmzettel unter\nTeilnehmerkennung ablegen
VS->MB:**receipt**
deactivate MB
deactivate VS
==Ende Abstimmungsphase==
|||
deactivate MB

@enduml

Message-Type: voting-definition
From: admin@partcp.example.org
To: partcp.example.org
Event-Id: 20211127-bundesparteitag-2021
Voting-Data:
  name: satzaend-031
  title: Satzungsänderungsantrag Nr. 31
  description: ...
  type: consensus-10
  options:
    - { id: 1, name: Passivlösung (keine Änderung) }
    - { id: 2, name: Änderung wird vorgenommen }
Message-Type: voting-details-request
From: p000063.4@partcp.example.org
To: partcp.example.org
Event-Id: 20211127-bundesparteitag-2021
Voting-Id: satzaend-031
Message-Type: voting-details
From: partcp.example.org
To: p000063.4@partcp.example.org
Original-Message: >
  ...
Voting-Data:
  id: satzaend-031
  created_on: 2021-11-27 12:53:09
  created_by: admin@partcp.example.org
  modified_on: 2021-11-27 12:55:39
  modified_by: admin@partcp.example.org
  status: open
  name: satzaend-031
  title: Satzungsänderungsantrag Nr. 31
  type: consensus-10
  options:
    - { id: 1, name: Passivlösung (keine Änderung) }
    - { id: 2, name: Änderung wird vorgenommen }
Message-Type: ballot
From: p000063.4@partcp.example.org
To: partcp.example.org
Event-Id: 20211127-bundesparteitag-2021
Voting-Id: satzaend-031
Votes:
  - { id: 1, vote: 7 }
  - { id: 2, vote: 0 }