Ga direct naar de documentatie
Kennisbank

End-to-end-versleuteling

OpenPGP-sleutels die in je browser worden gemaakt. Post die je naar een ander OpenEmail-adres stuurt kan verzegeld worden voordat ze het tabblad verlaat, en verzegelde post die aan jou is gericht opent in het leesvenster, ontsleuteld op jouw machine. De sleutels zijn nooit van ons om af te geven.

Details

  • Beide helften zijn end to end aangesloten. Opstellen aan een ontvanger wiens sleutel gepubliceerd is, verzegelt de berichttekst in de browser voordat het verzoek vertrekt; de server krijgt armor die hij niet kan lezen, markeert die als pgp-mime en bouwt een echt multipart/encrypted-bericht. Lezen gaat op dezelfde manier omgekeerd: de cijfertekst wordt opgehaald, in het tabblad ontsleuteld en als gewone post weergegeven.
  • Het algoritme is hetzelfde dat iedereen al gebruikt: OpenPGP, via openpgp.js, en PGP/MIME op de lijn. Een v4-sleutel op Curve25519, dezelfde vorm die Proton uitgeeft en die gpg met zijn standaard moderne algoritme produceert. Dus de post die dit leest is in principe dezelfde post die Thunderbird, gpg en Proton produceren, en niets hier is een eigen formaat dat later teruggedraaid zou moeten worden.
  • In de praktijk is het echter OpenEmail naar OpenEmail. Er is nergens in deze codebase een Web Key Directory, geen keyserver-opzoeking en geen verwerking van Autocrypt-headers: de enige plek waar de sleutel van een ontvanger ooit wordt gevonden is onze eigen directory, die sleutels bevat die vanuit deze app zijn gepubliceerd door mensen wier adres op een hier gehost domein staat. Er is ook geen manier om je sleutel uit te delen. De app publiceert je publieke helft in die directory en biedt er geen kopie of export van aan, dus een correspondent op Thunderbird heeft geen ondersteunde manier om hem te krijgen. Samenwerken met de bredere PGP-wereld is een eigenschap van het formaat, niet iets wat het product vandaag voor je doet.
  • Lezen is niet op die manier beperkt, want ontsleutelen heeft geen directory nodig. Elk PGP/MIME- of inline-PGP-bericht dat deze mailbox bereikt en verzegeld is aan een sleutel in deze browser, opent, wie het ook verstuurde en welke client hij ook gebruikte. Dat geldt ook voor berichten die verzegeld zijn aan een sleutel waar je sindsdien van weg bent geroteerd: uitgerangeerde sleutels blijven in de sleutelbos en worden naast de huidige geprobeerd, dus roteren kost je de post die je al ontving niet.
  • Groen betekent geopend, en het is op geen enkele andere manier te bereiken. De regel Details → Beveiliging wordt pas groen nadat een ontsleuteling in dit tabblad daadwerkelijk platte tekst heeft opgeleverd, nooit op grond van een veld op het bericht en nooit op grond van het feit dat er een versleutelde envelop binnenkwam. Er staat “End-to-end versleuteld. Geopend met jouw sleutel in deze browser”. Alles daaronder heeft zijn eigen zin in plaats van een gedeelde: nog aan het kijken, sleutel vergrendeld, verzegeld aan een sleutel die deze browser niet heeft, kon niet geopend worden, hier helemaal geen sleutel, en deze browser liet ons niet kijken. “We konden het niet controleren” en “jij hebt de sleutel niet” zijn verschillende uitspraken en de regel laat je lezen welke van de twee je kreeg.
  • S/MIME kan nog steeds niet geopend worden. Het is CMS onder een X.509-certificaat, openpgp.js kan er niet bij, en er is geen certificaatopslag in het product om de sleutel te bewaren als het wel kon, dus een S/MIME-bericht zegt dat OpenEmail het niet kan openen, en krijgt geen ontgrendeling aangeboden die niets zou doen.
  • De private helft wordt in je browser gegenereerd en verlaat hem nooit: niet versleuteld, niet in een back-up, niet in een supporttool. De server krijgt hem nooit, dus er is hier niets af te geven, te dagvaarden of te lekken. Hij wordt met een wachtwoordzin vergrendeld opgeslagen in een eigen IndexedDB-database, openemail-keyring, bewust buiten bereik van het advies “leeg je cache” en van de reset in de debugconsole: die wissen allebei de query-cache, en een sleutel die ernaast wordt bewaard zou routineus supportadvies elk versleuteld bericht dat het account ooit ontving permanent laten vernietigen. Je account verwijderen verwijdert hem wél, want daar gaat de post ook heen. Ontgrendelen houdt hem 15 minuten inactiviteit in het geheugen en maximaal 8 uur, waarna het volgende verzegelde bericht lezen opnieuw om de wachtwoordzin vraagt.
  • Er is geen escrow en geen herstel, en dat is permanent in plaats van ongebouwd. Je wachtwoordzin is de enige ingang; vergeet hem en elk bericht dat iemand aan jou verzegelde blijft op onze servers staan als cijfertekst die niemand kan lezen, wij incluis. De post is weg, en geen hoeveelheid vragen haalt hem terug. Het aanmeldscherm zegt dat voordat de eerste sleutel bestaat, achter een vinkje dat je moet aanzetten, en het back-upbestand is verplicht, en de knop Klaar blijft uitgeschakeld tot je het hebt gedownload. Dat bestand wordt bewust geschreven zonder de extra verharding in rust die deze browser gebruikt, zodat het nog steeds importeert in oudere gpg-builds: een back-up die je ergens anders niet kunt openen is geen back-up. De sleutel leeft ook in één browser op één apparaat, en een telefoon of een tweede laptop heeft niets tot je dat bestand daar importeert.
  • De directory bevat publieke sleutels en verder niets, en een sleutel hoort bij een persoon in plaats van bij een mailbox, want een sleutel die aan een adres hangt zou gekopieerd moeten worden naar iedereen met wie dat adres wordt gedeeld, wat escrow is onder een andere naam. Er een opzoeken vereist een ingelogde sessie en het recht om te versturen, nooit een openbaar endpoint, want een open adressondering is een orakel dat iedereen vertelt welke adressen hier levende mailboxen zijn. Het antwoordt identiek op “dat hosten we niet” en “dat hosten we en niemand heeft een sleutel gepubliceerd”, want die twee uit elkaar halen verplaatst het orakel alleen achter een login in plaats van het weg te nemen. En een sleutel wordt niet meer uitgedeeld zodra de eigenaar de toegang tot het adres verliest, in plaats van wanneer iemand eraan denkt hem in te trekken.
  • Elke byte wordt in de browser verzegeld op het moment dat je hem schrijft, en dat is wat de uitgestelde verzendingen überhaupt laat werken: een gepland bericht of een bericht dat in het ongedaan-maken-venster zit, wordt als cijfertekst opgeslagen en later verstuurd door een wachtrij die geen sleutel heeft en er niets van kan lezen. Een ontvanger wiens opzoeking in de directory MISLUKTE blokkeert de verzending in plaats van stilzwijgend te worden behandeld als iemand zonder sleutel. En een verzegeld bericht gaat alleen ooit uit over een pad dat een bericht in zijn geheel draagt. Een uitgaand pad dat in plaats daarvan een HTML-body aanneemt, zou de armor als zichtbare tekst plaatsen en succes melden, dus een verzending die daar zou landen wordt geweigerd voordat er een byte vertrekt in plaats van erna.
  • Wat verzegelen gaat kosten, gemeten in plaats van gegokt: de armor is ongeveer 1,86 keer de ruwe bytes, dus zo'n 2,7 MB aan bijlagen past binnen de 5 MB die het verstuurpad toestaat, en de composer weigert een payload daarboven voordat hij er seconden aan besteedt om er een te versleutelen die het transport toch zou weigeren. Versleutelde post rapporteert geen opens en geen kliks, want tracking per ontvanger werkt door de berichttekst per persoon te variëren en één verzegeld blok kan niet variëren, en een herschreven link is een link die wij kunnen lezen, wat het tegendeel van de claim is. Een versleutelde verzending kan ook nooit worden ontdubbeld met een idempotency key: een verse sessiesleutel maakt de cijfertekst bij elke poging andere bytes, dus een nieuwe poging heeft nooit dezelfde vingerafdruk als het origineel.
  • Plannen verzegelt op het moment van opstellen, niet op het moment van versturen. De composer bouwt de cijfertekst tegen de sleutels die zijn ontvangers hebben op de dag dat jij schrijft, niet op de dag dat het bericht zou vertrekken, de regel die dit product al toepast op sjablonen en vertalingen, waar een gepland bericht draagt wat jij hebt goedgekeurd in plaats van wat er daarna veranderde. Het verschil is dat een verouderd sjabloon slechts niet meer actueel is en een verouderde sleutel onleesbaar, dus de composer noemt de datum met zoveel woorden in plaats van een voorbehoud aan te bieden: “Nu verzegeld, verstuurd op …. Iedereen erop heeft de sleutel nodig die hij vandaag heeft.” De weigering die de andere helft bewaakt is geland maar is nooit afgegaan, omdat zo'n bericht nog niet kan bestaan: als het er wel was, zou het achteraf bewerken ervan geweigerd worden in plaats van stilletjes toegestaan, want de berichttekst patchen zou platte tekst over de cijfertekst schrijven en de ontvangers wijzigen zou wijzigen aan wie het verzegeld was, en allebei leveren in het open af terwijl elk scherm het nog versleuteld noemt.
  • Twee dingen die de composer helemaal niet aanbiedt, en dat zegt in plaats van op de lijn te falen. Een sjabloon wordt op de server gerenderd uit een gepubliceerde versie, dus er is niets in deze browser om te verzegelen. Een antwoord citeert het gesprek eronder en dat citaat wordt toegevoegd nadat de berichttekst verzegeld zou zijn, waardoor er een leesbare kopie van het hele gesprek buiten het zegel blijft liggen, dus antwoorden en doorsturen kunnen niet versleuteld worden zolang de geciteerde geschiedenis niet binnen de cijfertekst wordt gevouwen.
  • Niets hiervan verbergt je onderwerpregel, aan wie je schreef, of wanneer. Het onderwerp reist bij een verzegeld bericht net zo open over de lijn als bij elk ander, en het leesvenster zegt dat op het bericht zelf: “Het onderwerp en de adressen reisden in het open; deze tekst niet.” PGP dekt de berichttekst en geen enkele implementatie ervan dekt de rest. Concepten zijn ook onverzegeld, omdat automatisch opslaan platte tekst naar je mailbox blijft schrijven terwijl je opstelt, omdat stilletjes niet opslaan werk zou verliezen, en het hangslot maakt dat met zoveel woorden kenbaar.
  • Herkennen dat post verzegeld binnenkomt kwam eerst en geldt nog steeds. PGP/MIME, inline PGP-armor en S/MIME verschenen vroeger als een lege berichttekst met twee betekenisloze bijlagen, omdat de parser alleen platte tekst en HTML als leesbaar behandelt en de rest in de bestandenstrook liet vallen. Die onderdelen worden nu herkend, het protocolmeubilair blijft buiten de bijlagelijst, de cijfertekst wordt intact opgeslagen, wat is waaruit de lezer ontsleutelt in plaats van iets nieuws op te halen, en een bericht dat niemand hier kan openen zegt dat nog steeds ronduit.
  • Een ondertekend bericht wordt als iets aparts behandeld, want dat is het. De tekst ervan is leesbaar, dus zoeken, regels en al het andere blijven erop werken; het wordt nooit achter een slot gezet en nooit door een ontsleuteling gehaald. De regel meldt “Ondertekend door de afzender. Handtekening niet gecontroleerd”, gedimd, en die blijft gedimd tot er hier iets is dat een handtekening daadwerkelijk kan verifiëren, wat nog niets doet, ook niet bij een bericht dat met succes is ontsleuteld. Zien dat een bericht verzegeld is, is niet hetzelfde als het geopend hebben, en het openen is niet hetzelfde als weten wie het verzegelde.
  • Bij een versleuteld bericht wordt de berichttekst onthouden aan alles wat hem anders zou lezen: het zoekfragment, de tekstronde van de phishingscorer, de AI-schrijfcontrole, tekstvoorwaarden in regels, het importeren van agenda-uitnodigingen, en gesprekssamenvattingen. De authenticatiehelft van de phishingcontrole draait nog wel, omdat DMARC, DKIM en SPF van headers worden gelezen die cijfertekst niet verbergt. Ontsleutelen verandert daar niets aan. De platte tekst bestaat alleen in het tabblad dat hem opende, dus een verzegeld bericht blijft onvindbaar en blijft buiten de AI-functies, ook nadat je het hebt gelezen, en vertaling wordt er niet bij aangeboden. Dat is de prijs van de claim, geen omissie.