Encryptie

Asymmetrische encryptie

Een revolutie in digitale communicatie

Symmetrische encryptie is in veel opzichten krachtig: het is snel, efficiënt en relatief eenvoudig te implementeren. Maar het model heeft één groot nadeel: beide partijen moeten vooraf dezelfde geheime sleutel kennen, en die moet veilig worden uitgewisseld. In een digitale wereld waarin gebruikers zich wereldwijd bewegen en berichten voortdurend heen en weer gaan tussen onbekende netwerken, is dat een serieus probleem. Want hoe wissel je veilig een sleutel uit zonder dat die onderweg kan worden onderschept?

In de jaren ’70 leidde dit tot een fundamenteel nieuwe benadering: asymmetrische encryptie, ook wel bekend als public key encryption. De kern van dit systeem is dat gebruikers niet één enkele gedeelde sleutel hebben, maar een sleutelpaar: een publieke sleutel en een private sleutel. Deze twee sleutels horen bij elkaar, maar functioneren in tegengestelde richting.

Het principe

Het principe is verrassend eenvoudig, maar uiterst krachtig:

Bij asymmetrische encryptie worden meestal de volgende drie waarden gebruikt in de praktische toepassing (zoals in het vereenvoudigde JavaScript-script onderaan deze pagina):

  • Publieke sleutel (7 in het voorbeeld)
    • wordt gebruikt om te versleutelen
    • mag vrij gedeeld worden
  • Private sleutel (23 in het voorbeeld)
    • wordt gebruikt om te ontsleutelen
    • blijft geheim
  • Modulus (187 in het voorbeeld)
    • dit is het grote getal dat ontstaat door twee priemgetallen te vermenigvuldigen.
    • wordt gebruikt in zowel versleuteling als ontsleuteling, als modulus voor de berekening.

Met andere woorden: als jij iemand een geheim bericht wilt sturen, hoef je alleen zijn of haar publieke sleutel te kennen. Jij versleutelt het bericht daarmee, en alleen de persoon met de bijbehorende private sleutel kan het lezen. Zelfs jij kunt het versleutelde bericht niet meer teruglezen zonder de juiste sleutel.

Dit lost het centrale probleem van symmetrische encryptie op: je hoeft geen geheime sleutel uit te wisselen via een onveilig kanaal. De enige sleutel die je deelt, is de publieke, en die is juist bedoeld om vrij beschikbaar te zijn.

Eenrichtingsverkeer met wederzijds vertrouwen

Asymmetrische encryptie is gebaseerd op een speciaal type berekeningen die in één richting eenvoudig zijn, maar in omgekeerde richting praktisch onmogelijk. Je kunt bijvoorbeeld een groot getal makkelijk maken door twee grote priemgetallen met elkaar te vermenigvuldigen. Maar als je alleen het resultaat kent, is het extreem lastig om de oorspronkelijke priemfactoren te vinden. Deze eigenschap wordt gebruikt in algoritmes zoals RSA (Rivest–Shamir–Adleman), één van de bekendste asymmetrische encryptiesystemen.

De publieke sleutel is zo opgebouwd dat iedereen hem kan gebruiken om berichten te versleutelen, maar zonder de bijbehorende private sleutel is het terugrekenen van het originele bericht rekenkundig onhaalbaar, zolang de sleutels voldoende lang zijn.

Toepassingen in het dagelijks leven

Asymmetrische encryptie vormt de ruggengraat van veel technologieën die dagelijks gebruikt worden — vaak zonder dat we het beseffen:

  • SSL/TLS: De beveiliging van websites (herkenbaar aan het slotje in de adresbalk van je browser) is gebaseerd op asymmetrische encryptie. Als je een website bezoekt met HTTPS, wisselt je browser op de achtergrond sleutels uit om een veilige verbinding op te zetten.
  • E-mailversleuteling: Diensten zoals PGP (Pretty Good Privacy) gebruiken public key encryption om e-mails veilig te verzenden.
  • Digitale handtekeningen: Je kunt niet alleen berichten versleutelen, maar ook ondertekenen met je private sleutel. Iedereen die jouw publieke sleutel heeft, kan dan verifiëren dat het bericht echt van jou komt en onderweg niet is aangepast.
  • Cryptocurrencies: Bitcoin en andere digitale munten maken intensief gebruik van asymmetrische sleutelparen om eigendom, transacties en authenticatie te regelen.
Vertrouwen zonder voorkennis

Het concept van asymmetrische encryptie stelt gebruikers in staat om veilig te communiceren zonder dat ze elkaar eerder ontmoet hebben of op voorhand sleutels hebben uitgewisseld. Dat klinkt simpel, maar het is een revolutie in hoe veiligheid wordt georganiseerd op wereldschaal. Zonder deze technologie zouden online betalingen, beveiligde e-mails en vertrouwelijke overheidscommunicatie zoals we die nu kennen, niet mogelijk zijn.

Bovendien maakt asymmetrische encryptie het mogelijk om identiteit te bewijzen en vertrouwen op te bouwen zonder centrale autoriteit. Daarmee vormt het ook een belangrijke bouwsteen van decentrale systemen, zoals blockchaintechnologie.

In de les

In deze lessenserie gaan we het concept van asymmetrische encryptie niet alleen bespreken, maar ook ervaren. Je krijgt een vereenvoudigd script in JavaScript waarin je zelf een sleutelpaar gebruikt om berichten te versleutelen en ontsleutelen. Het gaat hier niet om het nabouwen van complexe standaarden, maar om het inzichtelijk maken van hoe het systeem werkt en waarom het veilig is — mits correct toegepast.

Tot slot

Asymmetrische encryptie is een voorbeeld van hoe abstracte wiskundige concepten vertaald kunnen worden naar concrete, praktische toepassingen met enorme impact. Het is een technologie die niet alleen wiskundig elegant is, maar ook maatschappelijk relevant en fundamenteel voor het vertrouwen in de digitale wereld.

Asymmetrische encryptie


Opdracht 2

Maak op je laptop weer een nieuw project en plak onderstaande code in de bestanden.
Bestudeer de code zorgvuldig. 
Zorg dat je de code goed begrijpt.

  • Voeg aan het javaScript comments toe waarin je uitlegt wat er gebeurt.
  • Maak in Lucidchart een flowchart waarin de werking van het versleutelen en het ontsleutelen verklaard wordt.
  • Download de flowchart als image en plaats de flowchart bij jouw werkende versleutelwidget.

Html

				
					<div class="wrapper" id="wrapper-asym">
  <h3>Asymmetrische encryptie</h3>
  <textarea id="bericht-asym" rows="4" placeholder="Voer bericht in"></textarea>
  <input type="number" id="sleutel-public" placeholder="Openbare sleutel (e)" value="7" disabled>
  <input type="number" id="sleutel-private" placeholder="Privésleutel (d)" value="23" disabled>
  <input type="number" id="modulus" placeholder="Modulus (n)" value="187" disabled>
  <pre id="output-asym"></pre><button id="versleutel-asym">Versleutel</button>
<button id="ontsleutel-asym">Ontsleutel</button></div>

JavaScript

				
					$(document).ready(function () {
    function modPow(base, exponent, modulus) {
        if (modulus === 1) return 0;
        let result = 1n;
        base = BigInt(base);
        exponent = BigInt(exponent);
        modulus = BigInt(modulus);
        while (exponent > 0n) {
            if (exponent % 2n === 1n) {
                result = (result * base) % modulus;
            }
            exponent = exponent / 2n;
            base = (base * base) % modulus;
        }
        return result; // LET OP: dit is een BigInt!
    }

    $("#versleutel-asym").click(function () {
        let tekst = $("#bericht-asym").val();
        let e = parseInt($("#sleutel-public").val());
        let n = parseInt($("#modulus").val());
        if (isNaN(e) || isNaN(n)) return;
        let versleuteld = [];

        for (let i = 0; i < tekst.length; i++) {
          let ascii = tekst.charCodeAt(i);
          versleuteld.push(modPow(ascii, e, n));
        }

        $("#output-asym").text(versleuteld.join(" "));
    });

    $("#ontsleutel-asym").click(function () {
        let d = parseInt($("#sleutel-private").val());
        let n = parseInt($("#modulus").val());
        if (isNaN(d) || isNaN(n)) return;
        let gecodeerdeTekst = $("#output-asym").text().split(" ");
        let origineel = "";

        for (let i = 0; i < gecodeerdeTekst.length; i++) {
            let code = parseInt(gecodeerdeTekst[i]);
            if (!isNaN(code)) {
                let asciiBig = modPow(code, d, n);   // dit is een BigInt
                let ascii = Number(asciiBig);        // converteer veilig
                // Sta gewone tekens én newline (ASCII 10) toe
                if ((ascii >= 32 && ascii <= 126) || ascii === 10) {
                    origineel += String.fromCharCode(ascii);
                } else {
                    origineel += "?";
                }
            }
        }

        $("#output-asym").text(origineel);
    });

});
				
			

CSS

				
					body {
  font-family: sans-serif;
  background-color: #f0f0f0;
}
#wrapper-asym {
  margin: 30px 3%;
  padding: 20px;
  width: 40%;
  background-color: #d0f0f0;
  border-radius: 12px;
}
textarea, input {
  width: 90%;
  margin: 10px 5%;
  padding: 5px;
  border-radius: 6px;
}
pre {
  margin: 10px 2% 10% 5%;
  padding: 10px;
  background: white;
  min-height: 80px;
  white-space: pre-wrap;
  word-wrap: break-word;
  border: 1px solid #ccc;
  border-radius: 6px;
}
button {
  margin: 5px 5%;
  padding: 8px 12px;
  border: none;
  background-color: teal;
  color: white;
  border-radius: 6px;
  cursor: pointer;
}
h3 {
  text-align: center;
}