Beveiliging

Hoe we het stemgeheim technisch afdwingen

Een OR-verkiezing staat of valt met vertrouwen. Daarom leggen we hier open hoe de database is gebouwd, geen marketingtaal, dit is de techniek zoals hij nu werkt. Klik een stap open voor het technische verhaal erachter.

✓Stemgeheim zit in het tabelontwerp, niet in een instelling
✓Elke stemlink is maar één keer te gebruiken
✓Verplicht versleuteld verkeer, overal (HTTPS + HSTS)
✓Technisch onmogelijk dat er geknoeid wordt met de resultaten
✓Gegevens verdwijnen automatisch na de bewaartermijn
✓Elke belangrijke actie ligt vast, zonder het stemgeheim te breken
✓Bescherming tegen geautomatiseerd misbruik op meerdere lagen
✓Gehost in Equinix AM6, Amsterdam: ISO 27001, PCI DSS en SOC 2 Type II-gecertificeerd
✓Dataservices 100% gehost in Nederland, geen data buiten de EU
Uitgangspunt

Het uitgangspunt: jij kunt niet zien op wie iemand stemde, wij ook niet

Wie mag stemmen en wat er gestemd is, staan in de database op twee volledig gescheiden plekken. Dat is geen instelling die je kunt aan- of uitzetten, het zit in hoe de tabellen zijn opgebouwd. Er bestaat geen kolom, geen rapport en geen beheerdersfunctie die een stem terugleidt naar een stemmer.

voters-tabel

Wie mag stemmen

  • Naam, e-mailadres, een gehashte versie van de unieke stemlink
  • Alleen: heeft deze persoon al gestemd? (ja/nee)
  • Geen enkel veld over de inhoud van de stem
Geen technische koppeling mogelijk
votes-tabel

Wat er gestemd is

  • Welke kandidaat, op welk moment
  • Geen naam, geen e-mailadres, geen stemmer-ID
  • Volledig los van de voters-tabel
Het datacenter

Waar je gegevens fysiek staan

Software is één laag, de fysieke plek waar de servers staan is een andere, en die telt net zo hard mee. Hieronder staat concreet waar dat is, niet alleen "in Nederland" maar het gebouw zelf, en wat daar allemaal voor gecontroleerd wordt.

Fysieke locatie

Equinix AM6, Amsterdam

OR StemTool draait op hosting van mijn.host. Mijn.host plaatst haar servers fysiek in het Equinix AM6-datacenter in Amsterdam, één van de grootste, zwaarst beveiligde datacenters van Nederland. Alle gegevens, inclusief de database met stemgerechtigden en stemmen, verlaten Nederland en de EU niet.

Extern gecertificeerd, niet ons eigen woord
Onafhankelijk getoetst

Niet alleen op slot, ook gecontroleerd

Een datacenter kan zelf beweren dat het veilig is, dat zegt weinig. Equinix AM6 wordt daarom periodiek doorgelicht door onafhankelijke auditors tegen internationale normen, hieronder staat waar elke certificering concreet voor staat.

✓ISO 27001 — informatiebeveiliging: risico's beheerst in plaats van ad hoc opgelost
✓ISO 22301 — bedrijfscontinuïteit: het datacenter blijft draaien bij een storing of calamiteit
✓SOC 2 Type II — beveiliging en beschikbaarheid getoetst over een langere periode, niet op één momentopname
✓SOC 1 Type II — interne controles rond de dienstverlening onafhankelijk gecontroleerd
✓PCI DSS — de zwaarste beveiligingsstandaard die er is voor het verwerken van betaalgegevens
✓ISO 9001 — kwaliteitsmanagement: processen aantoonbaar op orde, niet toevallig goed
✓ISO 45001 — arbeidsveiligheid voor iedereen die in het pand werkt
✓ISO 14001 & ISO 50001 — milieu- en energiemanagement, ook op datacenterniveau
✓EU Code of Conduct for Data Centres & Climate Neutral Data Centre Pact — energie-efficiëntie, met als doel in 2030 CO2-neutraal

Deze certificeringen gelden voor het Equinix AM6-gebouw waarin mijn.host haar servers plaatst, ze zijn te verifiëren op equinix.com. Los daarvan draait mijn.host zelf op 100% hernieuwbare energie (Garanties van Oorsprong), geverifieerd door de onafhankelijke Green Web Foundation, zie mijn.host/groene-hosting.

Stap voor stap

De reis van een verkiezing

Elke stap hieronder start met wat het jou oplevert. Klik 'm open voor de techniek erachter.

1
Alleen jij hebt toegang tot jouw verkiezing Echte accounts, geen geheime links
▾
Toegang loopt via een account: e-mailadres en wachtwoord, geen geheime link meer. Het wachtwoord wordt met bcrypt gehasht opgeslagen, dezelfde soort onomkeerbare versleuteling die banken gebruiken, wij kunnen je wachtwoord dus zelf ook niet terugzien. Bij het inloggen wordt de sessie ververst (voorkomt sessie-kaping), en na vijf mislukte inlogpogingen wordt een account 15 minuten vergrendeld, met een aantekening in het logboek. Wordt de aanbevolen bcrypt-sterkte later verhoogd, dan wordt jouw wachtwoord bij de eerstvolgende login automatisch stilzwijgend "opgewaardeerd".
2
Je verkiezing staat pas open als jij dat wilt Concept-status en account-gebonden limieten
▾
Een nieuwe verkiezing start altijd als "concept": nog niet zichtbaar voor stemgerechtigden, nog volledig aan te passen. Hoeveel verkiezingen één account per minuut kan aanmaken is bewust beperkt (rate limiting), zodat geautomatiseerd misbruik van dit formulier onmogelijk is. Elke verkiezing is gekoppeld aan precies één account, een organisator ziet en beheert alleen de eigen verkiezingen. Een poging tot andermans verkiezing levert altijd een neutrale "niet gevonden" op, geen "geen toegang", zo lekt zelfs het bestáán van andermans verkiezing niet.
3
Zodra een verkiezing actief is, kan de configuratie niet meer gewijzigd worden Onwijzigbaar na activatie, op databaseniveau, ook niet voor ons
▾
Zodra een verkiezing geactiveerd wordt, kunnen kandidaten en stemgerechtigden niet meer gewijzigd worden, dat wordt afgedwongen met databasetriggers, niet alleen doordat de applicatie er geen functie voor aanbiedt. Ook een kernveld van de verkiezing zelf (naam, bedrijf, type, openings- en sluitingstijd) kan na activatie niet meer aangepast worden, precies om te voorkomen dat een actieve verkiezing stilletjes verlengd of aangepast zou kunnen worden. Activeren zelf kan bovendien maar één kant op: van "concept" naar "actief". Een verkiezing die al gesloten is, kan onmogelijk per ongeluk of moedwillig opnieuw "actief" gezet worden, ook dat wordt op databaseniveau tegengehouden, niet alleen door een schermpje dat een knop verbergt.
4
Zelfs bij een volledige databasekopie is niet te herleiden wie op wie heeft gestemd Cryptografisch willekeurige, gehashte tokens
▾
Elke stemgerechtigde krijgt een unieke, cryptografisch willekeurige stemlink. Die link zelf staat nergens in de database, alleen een gehashte (onomkeerbare) versie ervan, hetzelfde principe als een wachtwoord. Bij een eventueel datalek zijn er dus geen bruikbare stemlinks buit te maken, alleen onbruikbare vingerafdrukken, en zoals hierboven al staat: de stem zelf is in de database sowieso nergens aan een stemmer gekoppeld.
5
Een stemlink is onderweg nergens af te luisteren of dubbel te gebruiken HTTPS overal, token uit de URL, databasevergrendeling
▾
Open je een stemlink, dan wordt het token daarin meteen overgeheveld naar een korte, aparte sessie en verdwijnt het uit de adresbalk, zo blijft het niet staan in browsergeschiedenis of een schermafbeelding, en komt het nooit in een tweede of latere request voor. Alleen die allereerste, versleutelde (HTTPS) aanvraag met het token kan in theorie nog kort in de toegangslogs van de webserver zelf belanden, vóórdat de doorverwijzing plaatsvindt, dat is inherent aan een link die überhaupt éénmalig moet binnenkomen, en geldt evengoed voor bijvoorbeeld een "wachtwoord vergeten"-link. Al het verkeer gaat verplicht via HTTPS (automatische doorverwijzing plus een HSTS-header), en de Referrer-Policy staat op no-referrer, zodat een stemlink nooit via een verwijzings-header bij een andere website terecht kan komen. Bij het daadwerkelijk uitbrengen van de stem wordt met een technische databasevergrendeling gecontroleerd of het token al gebruikt is, vóórdat de stem wordt weggeschreven, twee vensters tegelijk openen levert dus nooit een dubbele stem op. De stem zelf komt terecht in de aparte, niet aan een stemmer te koppelen tabel uit stap 1.
6
Jij ziet wie nog moet stemmen, nooit wat iemand gestemd heeft Status-only inzage, tokens die zelf verlopen
▾
Een organisator ziet per stemgerechtigde alleen of er al gestemd is, nooit wat iemand gestemd heeft, dat is met de huidige opzet ook technisch onmogelijk te tonen. Stuur je een (nieuwe) stemlink of herinnering, dan wordt er een gloednieuw token gegenereerd en het vorige pas ongeldig gemaakt ná een geslaagde verzending, zoals een "wachtwoord vergeten"-link. Een oude, mogelijk elders beland kopie van de link werkt daarna niet meer, en een mislukte verzending laat nooit iemand met een kapotte link achter.
7
Na sluitingstijd stemmen of het proces beïnvloeden kan niet meer Automatische, onomkeerbare sluiting
▾
Zodra de ingestelde stemperiode voorbij is, wordt de verkiezing niet stilzwijgend "actief" gelaten totdat er toevallig iemand naar kijkt: bij het eerstvolgende verzoek wordt hij expliciet en met tijdstip vastgelegd als "gesloten". Vanaf dat moment verdwijnen de activeer- en herinneringsknoppen uit het dashboard, en weigert de server, met een harde foutcode, niet alleen een verborgen knop, elke poging om nog stemmen of herinneringen te versturen voor die verkiezing.
8
De uitslag is achteraf aantoonbaar niet geknoeid Hashbaar, controleerbaar verkiezingsrapport
▾
Zodra een verkiezing gesloten is, berekent het systeem de opkomst en de stemmen per kandidaat, en legt daar bij de allereerste opvraging een sha256-hash van vast, een digitale vingerafdruk van de exácte uitslag op dat moment. Bij elke latere opvraging wordt die hash opnieuw berekend en vergeleken met de vastgelegde versie. Komen ze niet meer overeen, dan meldt het rapport dat expliciet (het faalt zichtbaar, in plaats van stilzwijgend een mogelijk geknoeide uitslag te tonen), en dat wordt ook in het logboek vastgelegd.
9
Elke belangrijke actie is achteraf controleerbaar Append-only logboek, stemgeheim-getoetst
▾
Een append-only logboek registreert de belangrijke gebeurtenissen: geregistreerd, ingelogd, mislukt ingelogd, account vergrendeld, verkiezing aangemaakt/geactiveerd/gesloten, herinneringen verstuurd (alleen de aantallen), en een geldige stem ontvangen. Bij dat laatste staat er alleen "er is een geldige stem binnengekomen bij verkiezing 123", nooit wélke stem, wélke kandidaat of van wíe. Er bestaat in de hele applicatie geen functie om een logregel te wijzigen of te verwijderen, alleen toevoegen kan.
10
Gegevens blijven nooit langer bestaan dan nodig Automatische verwijdering na de bewaartermijn
▾
Een gesloten verkiezing krijgt automatisch een bewaartermijn van 12 maanden. Daarna worden de verkiezing, de kandidaten, de stemgerechtigden en alle stemmen automatisch en onomkeerbaar verwijderd, zonder dat daar een handeling van de organisator voor nodig is. Alleen een anonieme logregel dat en wanneer die opschoning heeft plaatsgevonden blijft daarna nog bestaan, zonder naam- of verkiezingsgegevens.

AVG: een bouwsteen, geen garantie op zich

Data-soevereiniteit (zie hierboven) helpt bij AVG-naleving, maar is niet hetzelfde. Zie onze privacyverklaring voor de rest van het plaatje: wat we vastleggen, hoelang, en waarom.

Niet alleen gebouwd, ook getest

Deze werking is doorlopen met een testverkiezing: registreren, aanmaken, activeren, stemmen, een tweede stempoging laten weigeren, controleren dat een ander account geen toegang krijgt, kunstmatig sluiten en het rapport met hash laten genereren.

Onze standaardtest: het "database compromise thought experiment" Hoe we bij elke test het stemgeheim zelf op de proef stellen
▾
Bij elke test die met stemgeheim te maken heeft, stellen we ons voor dat iemand alléén een volledige databasekopie in handen krijgt, kan die persoon dan herleiden wie op wie heeft gestemd? Het antwoord moet nee zijn. Hetzelfde gedachte-experiment herhalen we met database + logboek, en met database + logboek + e-mailgegevens. Zodra bij één van die scenario's de koppeling tussen stemmer en stem reconstrueerbaar zou worden, is dat iets om expliciet op te bouwen en te testen, niet iets waar we alleen op vertrouwen omdat het tabelontwerp het "in theorie" voorkomt.

Vragen over hoe dit voor jouw organisatie werkt?

Neem gerust contact op voordat je een verkiezing activeert.

Neem contact op