RSA Inleiding RSA is een encryptiemethode die in 1977 beschreven werd door Ron Rivest, Adi Shamir en Leonard Adleman (vandaar de naam RSA). Als je de RSA-methode veilig wilt gebruiken moet je heel grote priemgetallen1 gebruiken bij de codering. In de uitleg hieronder gaan we uit van kleine priemgetallen, omdat dat gemakkelijker leest. Als je rechtsboven een woord of zin een getal ziet staan wil dat niet zeggen dat je dat woord of die zin tot die macht moet verheffen, maar er staat dan wel een voetnoot onderaan de pagina. In de coderingstheorie worden de ontvanger en verzender van een bericht vaak Alice en Bob genoemd (afgekort als A en B). Bij deze opdracht houden we ons aan die traditie. De methode voorbereiding Schrik niet! Er komt nogal wat wiskunde kijken bij het versleutelen met RSA. Alice gaat als volgt te werk: Kies twee verschillende priemgetallen p en q Bereken n= pq n = p− 1 q− 1 Bereken de zogenaamde totiënt: n ligt en dat geen deler met Kies een getal e dat tussen 1 en 2 e heeft . vormt samen met n de publieke sleutel. Bereken d zodat de≡ 1 mod n 3 4. d vormt samen met n de geheime sleutel. Vernietig p en q. n gemeenschappelijk 1 Een priemgetal is een geheel positief getal groter dan 1, dat alleen door zichzelf en 1 deelbaar is. Vier is dus geen priemgetal omdat het ook deelbaar is door twee. 2 3 en 9 hebben 3 als gemeenschappelijke deler. 8 en 12 hebben 2 als gemeenschappelijke deler. Er is altijd een kleinste gemeenschappelijke deler (de KGV). Als die 1 is hebben de twee getallen geen echte deler gemeenschappelijk. 3 Als a≡ b mod n is b de rest van de deler a gedeeld door n. Dus 7≡ 1 mod 3 . Als k het aantal keer is dat n op a te delen is geldt dus 7= 1 3k . In NSBasic bereken je dit met a=mod(b,n) en in Pascal/Delphi met a:=b mod n n bij 1 op te tellen en dan te kijken of je e er precies op kunt delen. De uitkomst is 4 Je kunt dat dus doen door dan d. Coderen/versleutelen van de boodschap Alice stuurt n en e naar Bob. d houdt ze geheim. Als Bob nu een bericht B naar Alice wil sturen moet hij het volgende doen. Allereerst moet hij het bericht in een getal m omzetten5. M moet daarbij kleiner dan n zijn. Als m groter dan n is, moet hij het bericht in kleiner stukken verdelen. De gecodeerde tekst (het in inmiddels een getal) berekend hij dan met: c= me mod n Alle getallen c stuurt Bob nu in de juiste volgorde naar Alice. Als we bijvoorbeeld de getallen 83, 6, 873 willen sturen moeten we er een scheidingsteken tussen zetten (in deze tekst is dat een komma, maar het mag ook iets anders zijn). We kunnen er ook voor kiezen om de getallen even lang te maken, door er nullen voor te plakken. We kunnen ze dan wel achterelkaar plakken: 083006873. In dit voorbeeld hebben we nullen voor het getal geplakt tot de lengte drie was. Omdat de nul in deze gecodeerde tekst wel heel erg vaak voorkomt zal een fraudeur al snel op het idee komen dat we de getallen met nullen aangevuld hebben. De conclusie dat de getallen maximaal 3 cijfers lang zijn, is dan niet meer zo moeilijk6. Decoderen/ontsleutelen van de boodschap Alice ontvangt een aantal getallen c. Elke getal rekent ze dan weer om naar m op de volgende manier: m= c d mod n Bewijzen dat dit klopt, is (mooie) wiskunde. Voorbeeld We gaan de methode nu met concrete getallen illustreren. Kies twee verschillende priemgetallen p en q : p=53 en q=61 Bereken n= pq : n=53*61=3233 n = p− 1 q− 1 :(61-1)*(53-1)=3120 Bereken de zogenaamde totiënt: n ligt en dat geen deler met n gemeenschappelijk Kies een getal e dat tussen 1 en heeft7. We kiezen voor e= 17 .8 5 De methode die Bob gebruikt om M in m om te zetten moet natuurlijk omkeerbaar zijn, zodat Alice m in M kan omzetten. Alice moet natuurlijk weten hoe ze dat moet doen. Een eenvoudige (en niet zo veilige methode) is het gebruiken van de ASCII-waarde van een teken (waarom is dat niet veilig?). Het wordt al wat moeilijker als je meer dan 1 teken tegelijk in het getal verwerkt. Je zou de tekenreeks AB kunnen omzetten naar een getal met g=256*ASC('A')+ASC('B'). 6 Je kunt de getallen ook met behulp van een wiskundige functie omrekenen naar een ander getal dat maximaal drie 127 cijfers langs is, bijvoorbeeld: g = m mod 1000 7 3 en 9 hebben 3 als gemeenschappelijke deler. 8 en 12 hebben 2 als gemeenschappelijke deler. Er is altijd een kleinste gemeenschappelijke deler (de KGD). Als die 1 is hebben de twee getallen geen echte deler gemeenschappelijk. 8 Als je voor e een priemgetal kiest, heb je zeker een getal dat geen deler de totiënt gemeenschappelijk heeft. Bereken d zodat de≡ 1 mod n k=15, dan vinden we d=2753. Vernietig p en q.11 9 10 . We proberen achtereenvolgens k=1, k=2, k=3,... Bij Als Bob nu het teken { willen coderen, kan dat als volgt: 17 De ASCII-waarde van { is 123. Dus m= 123 . c= 123 mod 3233= 855 . 2753 Alice vindt de oorspronkelijke boodschap weer met m= 855 mod 3233= 123 . Kies natuurlijk willekeurig. 9 Als a≡ b mod n is b de rest van de deler a/n. Dus 7≡ 1 mod 3 . Als k het aantal keer is dat n op a te delen is geldt dus 7= 1 3k . n bij 1 op te tellen en dan te kijken of je e er precies op kunt delen. De uitkomst is 10 Je kunt dat dus doen door dan d. 11 Oeps... Details kies k=15 Er zijn een aantal plekken waar je tegen problemen aanloopt. Zo stellen we in de voorlaatste stap dat je d wel kon vinden door k=15 te kiezen. Maar hoe weet je dat? Dat weet je inderdaad niet 1-2-3. Wiskundige gezien moet je de inverse van d modulo n uitrekenen. n −1 mod n , dus in het geval van Dat kan met het algoritme van Euclides. Daaruit volgt dat d = e 3119 het voorbeeld d = 17 mod 3120 . Als je dat algoritme te ingewikkeld vindt, kun je ook achtereenvolgens k=1, k=2, …, etc. proberen. Voorbeeld: k=1 d⋅ 17≡ 1 k⋅ 3120 d⋅ 17≡ 1 1⋅ 3120 d⋅ 17≡ 3121 d ≡ 3121/17≈ 183,6 d is geen geheel getal, we moeten dus de volgende waarde van k proberen. 2753 Bereken m= 855 mod 3233= 123 2753 Hoe reken je dit uit? Je doet dat niet door 855 te berekenen. De rekenmachine van Windows 8071 zegt dat dit ongeveer 5,05× 10 . Dat is dus een getal van 8072 cijfers! Aangezien in 16 bits hooguit het getal 65535 past, zal dit getal dus zeker niet passen. Rekenen met kommagetallen is geen optie omdat we de exacte rest moeten berekenen. (Leuke vraag: hoeveel bits zou je nodig hebben om dit getal op te slaan?12) We berekenen het als volgt: m= 1 m= 1× 855 mod 3233= 855 m= 855× 855 mod 3233= 367 m= 367× 855 mod 3233= 184 ... ... Op deze manier vermenigvuldigen we 2753 maal met 855. Het tussenresultaat blijft dus steeds kleiner dan 855x3233=2764215. Dat past in een integer. 8071 12 Bereken log 5,04× 10 /log 2= 26813 (bits). In pseudocode zou dat er zo uit kunnen zien: macht=2753 uitkomst=1 e=855 n=3233 for teller=1 to macht uitkomst=mod(uitkomst*e,n) next Hoe bepaal je de ASCII-waarde van een letter? In Delphi gaat dat als volgt: Ga er van uit dat s een string is die een tekst bevat. Het i-de teken lees je dan uit met s[i]. Het aantal tekens in s bepaal je met length(s). De ASCII-waarde van dat teken bepaal je met ord(). Hieronder staat pseudocode // declaraties van de variabelen var s,t:string; i:integer; // bepalen van alle ASCII-waarden van de tekens in s for i:=1 to length(s) do begin t:=s[i]; showmessage(IntToStr(Ord(t)); end; Hoe bepaal je het teken dat bij een ASCII-waarde hoort? Met de functie chr() krijg je het teken dat bij een ASCII-waarde hoort. Stel dat je een string wilt maken van de 3 ASCII-waarden 65, 66 en 67. Dan kan dat als volgt: s := chr(65)+chr(66)+chr(67); Hoeveel tekens tegelijk coderen? Coderen per teken (dus voor 1 teken tegelijk) is onzinnig omdat je nog steeds kunt tellen welke letters het meeste voorkomen. Dezelfde letter worden immers op dezelfde manier gecodeerd: als een 65 (ASCII-code van 'A') gecodeerd wordt tot 213, dan worden alle A's als 213 gecodeerd. Je moet daarom voor een groepje letters coderen. Hoe vat je drie ASCII-waarden in één getal samen? Het decimale getal 123 bestaat uit 3 tekens: 1, 2 en 3. Elke positie kan maximaal de waarde negen hebben. 2 De waarde van de drie tekens is 1× 10 2× 10 3× 1 Als je drie tekens codeert gaat dat bijna hetzelfde. Neem bijvoorbeeld de string 'ABC'. Die bestaat uit de tekens 'A', 'B', 'C'. Elke teken heeft een ASCII-waarde: 'A' → 65, 'B' → 66, 'C' → 67. De waarde van een ASCII-waarde is minimaal 0 en maximaal 255. We kunnen de string 'ABC' dus de volgende waarde geven: 65× 2562 66× 256 67× 1= 4276803 Bij decimale getallen is het niet moeilijk om uit een getal de eenheden, tientallen, en honderdtallen te halen. Met moet daarvoor de rest bij deling kunnen bepalen. Voorbeeld 7 : 3 = 2 rest 1 Je berekent in Delphi de rest met de opdracht mod: rest := 7 mod 3; //in rest staat nu de waarde 1 We nemen als voorbeeld het getal 987. Hoeveel eenheden zitten er in 987? 987 : 10 = 98 rest 7 → dus 7 eenheden bereken nu (987 – 7) : 10 = 98 De 8 van 98 staat in het getal 98 voor de eenheden, maar in het oorspronkelijke getal de tientallen. Hoeveel tientallen zitten er in 987? 98 : 10 = 9 rest 8 → dus 8 tientallen Bereken nu (98 – 8) : 10 = 9 De 9 zijn eenheden, maar in het oorspronkelijke getal de honderdtallen. Hoeveel honderdtallen zitten er in 987? 9 : 10 = 0 rest 9 → dus 9 honderdtallen Op dezelfde manier kunnen we het getal 4276803 terugrekenen naar de drie losse ASCII-waarden. 4276803 : 256 = 16706 rest 67 16706 : 256 = 65 rest 66 65 : 256 = 0 rest 65 Je ziet dus dat de drie oorspronkelijke ASCII-waarde als rest uit de berekeningen komen. Grote getallen Als je met heel grote getallen wilt kunnen rekenen kun je deze bibliotheek met speciale rekenfuncties gebruiken. Opdracht 1 Maak in je Google Account een spreadsheet aan waarin je bijhoudt wanneer je aan het programma gewerkt hebt. Deel dat document met [email protected] zodat het document te lezen is (en dus niet te bewerken). Vermeld elke keer het volgende: datum, starttijd, eindtijd, totale tijd wat is er gedaan Opdracht 2 Je docent geeft je 1 van de volgende opdrachten: Schrijf een programma dat d, e, n berekent. Schrijf een programma dat een bericht codeert met e,n. Het versleutelde bericht moet in een emailbericht te plakken zijn. Schrijf een programma dat een bericht decodeert met d,n. Het gedecodeerde bericht moet te kopiëren zijn naar een tekstverwerker. De programma's moeten zo gemaakt zijn dat ze met elkaar samen kunnen werken. Daarbij moet je een aantal problemen oplossen: hoe zet je een tekst om naar getallen hoe zet je dat getal om naar een getal met een vaste lengte, etc. Al deze omzettingen moeten natuurlijk ook in omgekeerde richting werken. Extra 1: Als je in het bestand een username/usercode opneemt kan het programma zelf de juiste sleutel er bij zoeken. Extra 2: Bij de laatste twee programma's verdien je pluspunten als je drag and drop implementeert: als je een bestand op het venster sleept wordt het meteen gedecodeerd. Je kunt kiezen uit de programeer talen Python, Java, NS-Basic, Delphi. Opdracht 3 Vermeldt in je logboek hoeveel tijd je aan de opdracht gewerkt heb, en hoeveel tijd jouw groepsgenoten naar schatting aan de opdracht gewerkt hebben. Nabespreking - Relatieve en absolute tijdsbesteding - Ontwerpmethode: Ontwerpen, implementeren en testen