def stringToByteList(s): """ wandelt ein Zeichenkette in eine Byteliste um; die Codierung erfolgt mit UTF-8 >>> stringToByteList('Schlüsselpaar') [83, 99, 104, 108, 195, 188, 115, 115, 101, 108, 112, 97, 97, 114] """ return list(bytes(s, 'utf8')) def blocklaenge(n): """ bestimmt die maximale Blocklänge bei vorgebenem n >>> blocklaenge(3001122295343) 5 """ i = 0 potenz256 = 1 while potenz256-1 <= n: potenz256 = potenz256 * 256 i = i + 1 return i-1 def byteListToNat(byteListe): """ erzeugt aus einer Liste von Bytes eine natürliche Zahl >>> byteListToNat([83, 99, 104, 108, 195]) 358150073539 """ i = len(byteListe)-1 zahl = 0 for byte in byteListe: zahl = zahl + byte*256**i i = i-1 return zahl def byteListToNatList(byteListe, blocklaenge): """ wandelt ein Liste von Bytes in eine Liste mit Zahlen um; berücksicht dabei eine vorgegebene Blocklänge >>> byteListToNatList([83, 99, 104, 108, 195, 188, 115, 115, 101, 108, 112, 97, 97, 114], 5) [358150073539, 809390794092, 1885430130] """ natListe = [] while byteListe != []: block = byteListe[0:blocklaenge] natListe = natListe + [byteListToNat(block)] byteListe = byteListe[blocklaenge:] return natListe def natToByteList(zahl): """ wandelt eine natürliche Zahl in eine Liste mit Bytes um; >>> natToByteList(358150073539) [83, 99, 104, 108, 195] """ byteListe = [] while zahl > 0: byteListe = [zahl%256] + byteListe zahl = zahl//256 return byteListe def natListToByteList(natListe): """ wandelt eine Liste mit natürlichen Zahl in eine Liste mit Bytes um; >>> natListToByteList([358150073539, 809390794092, 1885430130]) [83, 99, 104, 108, 195, 188, 115, 115, 101, 108, 112, 97, 97, 114] """ byteListe = [] for zahl in natListe: byteListe = byteListe + natToByteList(zahl) return byteListe def natToByteListErweitert(zahl, blocklaenge): """ wandelt eine natürliche Zahl in eine Liste mit Bytes um; berücksicht dabei eine vorgegebene Blocklänge und füllt die Liste mit Nullen auf >>> natToByteListErweitert(1885430130, 6) [0, 0, 112, 97, 97, 114] """ byteListe = natToByteList(zahl) while len(byteListe) < blocklaenge: byteListe = [0] + byteListe return byteListe def natListToByteListErweitert(natListe, blocklaenge): """ wandelt eine Liste mit natürlichen Zahl in eine Liste mit Bytes um; berücksicht dabei eine vorgegebene Blocklänge und füllt die Liste mit Nullen auf >>> natListToByteListErweitert([358150073539, 809390794092, 1885430130], 6) [0, 83, 99, 104, 108, 195, 0, 188, 115, 115, 101, 108, 0, 0, 112, 97, 97, 114] """ byteListe = [] for zahl in natListe: byteListe = byteListe + natToByteListErweitert(zahl, blocklaenge) return byteListe def modpot(x, y, m): """ berechnet (schnell) die modulare Potenz >>> modpot(52, 37, 77) 24 """ pot = 1 while y > 0: if y % 2 == 1: pot = (pot * x) % m y = y - 1 else: x = (x * x) % m y = y // 2 return pot def verschluesselnNat(zahl, schluessel): """ verschluesselt durch modulare Potenzbildung >>> verschluesselnNat(358150073539, (65537, 3001122295343)) 2465016304633 >>> verschluesselnNat(2465016304633, (2384015708753, 3001122295343)) 358150073539 """ return modpot(zahl, schluessel[0], schluessel[1]) def verschluesselnNatList(zahlenListe, schluessel): """ verschluesselt eine Zahlenliste durch modulare Potenzbildung >>> verschluesselnNatList([358150073539, 809390794092, 1885430130], (65537, 3001122295343)) [2465016304633, 2630297697622, 381401817373] >>> verschluesselnNatList([2465016304633, 2630297697622, 381401817373], (2384015708753, 3001122295343)) [358150073539, 809390794092, 1885430130] """ liste = [] for zahl in zahlenListe: liste = liste + [verschluesselnNat(zahl, schluessel)] return liste def codieren(zeichenkette): """ erzeugt aus einer Zeichenkette eine Bytefolge >>> codieren('öffentlicher Schlüssel') [195, 182, 102, 102, 101, 110, 116, 108, 105, 99, 104, 101, 114, 32, 83, 99, 104, 108, 195, 188, 115, 115, 101, 108] """ return stringToByteList(zeichenkette) def verschluesseln(byteListe, schluessel): """ erzeugt aus einer Liste aus Bytes (zu einer Zeichenkette) eine Bytefolge (zu einer Zahlenfolge) >>> verschluesseln([195, 182, 102, 102, 101, 110, 116, 108, 105, 99, 104, 101, 114, 32, 83, 99, 104, 108, 195, 188, 115, 115, 101, 108], (65537, 3001122295343)) b'\x00\x10\xf0\x1e\x1e\xc1\x02\t\x9a\x1e\x17\x87\x02\x0e\x05\xb5T\xb2\x01*\x1ckX\x9e\x00\xc4\x04\xeem\xc4' """ #print('Byteliste:', byteListe) n = schluessel[1] b = blocklaenge(n) #print('Blocklänge:', b) natListe = byteListToNatList(byteListe, b) #print('Zahlenliste:', natListe) natListeVerschluesselt = verschluesselnNatList(natListe, schluessel) #print('Zahlenliste:', natListeVerschluesselt) byteListeVerschluesselt = natListToByteListErweitert(natListeVerschluesselt, b+1) #print('Byteliste:', byteListeVerschluesselt) byteFolge = bytes(byteListeVerschluesselt) #print('Bytefolge:', byteFolge) return byteFolge def entschluesseln(byteFolge, schluessel): """ erzeugt aus einer Bytefolge eine Byteliste >>> entschluesseln(b'\x00\x10\xf0\x1e\x1e\xc1\x02\t\x9a\x1e\x17\x87\x02\x0e\x05\xb5T\xb2\x01*\x1ckX\x9e\x00\xc4\x04\xeem\xc4', (2384015708753, 3001122295343)) [195, 182, 102, 102, 101, 110, 116, 108, 105, 99, 104, 101, 114, 32, 83, 99, 104, 108, 195, 188, 115, 115, 101, 108] """ #print('Bytefolge:', byteFolge) n = schluessel[1] b = blocklaenge(n) #print('Blocklänge:', b) byteListe = list(byteFolge) #print('Byteliste:', byteListe) natListe = byteListToNatList(byteListe, b+1) #print('Zahlenliste:', natListe) natListeEntschluesselt = verschluesselnNatList(natListe, schluessel) #print('Zahlenliste:', natListeEntschluesselt) byteListeEntschluesselt = natListToByteList(natListeEntschluesselt) #print('Byteliste:', byteListeEntschluesselt) return byteListeEntschluesselt def decodieren(byteListe): """ erzeugt aus einer Byteliste eine Zeichenkette >>> decodieren([195, 182, 102, 102, 101, 110, 116, 108, 105, 99, 104, 101, 114, 32, 83, 99, 104, 108, 195, 188, 115, 115, 101, 108]) 'öffentlicher Schlüssel' """ return str(bytes(byteListe), 'utf8') def verschluesselnDatei(quelldatei, zieldatei): """ verschlüsselt den Quelltext aus einer Quelldatei und speichert ihn in einer Zieldatei """ datei = open(quelldatei, "r") quelltext = datei.read() datei.close() byteListe = codieren(quelltext) byteFolge = verschluesseln(byteListe, oeffentlicherSchluessel) datei = open(zieldatei, "wb") datei.write(byteFolge) datei.close() def entschluesselnDatei(quelldatei, zieldatei): """ entschlüsselt den Code aus einer Quelldatei und speichert ihn in einer Zieldatei """ datei = open(quelldatei, "rb") byteFolge = datei.read() byteListe = entschluesseln(byteFolge, privaterSchluessel) quelltext = decodieren(byteListe) datei = open(zieldatei, "w") datei.write(quelltext) datei.close() def ggt(a,b): """ berechnet iterativ den ggt von a und b """ while b > 0: (a,b) = (b,a%b) return a def erweiterterEuklidischerAlgorithmus(a, b): """ bestimmt die Darstellung von a und b nach dem Lemma von Bachet >>> erweiterterEuklidischerAlgorithmus(884, 320) (4, 21, -58) """ aalt = a amitte = b xalt = 1 xmitte = 0 yalt = 0 ymitte = 1 while amitte != 0: q = aalt // amitte aneu = aalt - q * amitte xneu = xalt - xmitte * q yneu = yalt - ymitte * q xalt = xmitte xmitte = xneu yalt = ymitte ymitte = yneu aalt = amitte amitte = aneu return (aalt, xalt, yalt) def modInv(a, m): """ bestimmt das modulare Inverse zu d bzgl. m mit dem erweiterten euklidischen Algorithmus >>> modInv(7, 30) 13 """ (ggt, x, y) = erweiterterEuklidischerAlgorithmus(a, m) if ggt > 1: return -1 else: if x < 0: x = x + m return x def kryptosystemRSA129(): """ basierend auf rsa-129 wird ein 'Spiel-Krypto-System' (e,d,n) zurückgegeben """ p = 3490529510847650949147849619903898133417764638493387843990820577 q = 32769132993266709549961988190834461413177642967992942539798288533 assert p*q == 114381625757888867669235779976146612010218296721242362562561842935706935245733897830597123563958705058989075147599290026879543541 n = p*q phi = (p-1)*(q-1) e = 4321 assert ggt(e, phi) == 1 d = modInv(e, phi) return (e, d, n)