Enigma Machine, I need help! - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: General Coding Help (https://python-forum.io/forum-8.html) +--- Thread: Enigma Machine, I need help! (/thread-6259.html) |
RE: Enigma Machine, I need help! - Larz60+ - Nov-27-2017 Quote:So thamk you a lot, and it isn't too urgent that it is done, it just sounded you were near to doneIn programming, it's always almost done., let me just say there's more to do, and set a goal for next weekend. Right Now, I'm working on the graphics for the plug board. Here's what the first row of plugs looks like so far (click to enlarge): [attachment=298] when you click on a letter, and then another, the centers will change color, 13 different colors for all pairs. I'm pretty satisfied with the operation of the module Incrementor.py. You can download it, and play with it, as it has code to run standalone, or imported into full project. It can do all of cipher, less the plug board. Once the plugboard is done, I'll put it all together and you can add the gui. The plugboard gui can be imported into the main gui as it uses a parent window to draw in. all you will have to do to make it work, it to provide the parent location, and it will draw there. [align=initial !important] I also thought it would be fun to add a lamp gui, but that would probably take another few days. I'll keep you updated here's the full GUI, not connected yet, but I will put the code on Github in the next few minutes. [attachment=300][/align] RE: Enigma Machine, I need help! - Larz60+ - Nov-28-2017 Patchboard is partially working now, enough to play with it and get an idea of where I'm heading with it. remaining issues:
I am also going to take the time to synchronize with GitHub so code is always up to date (have to put the hooks into PyCharm). RE: Enigma Machine, I need help! - Larz60+ - Nov-29-2017 Patchboard is done except for small change. Needs a 'Done' button, and remove print statement which i left in for now because it shows expansion and shrinking of patchboard as plugs are added and removed. As always can be tested by running: Python PatchBaord.pyand module is up to date in github (I can now do pushes directly from PyCharm) RE: Enigma Machine, I need help! - sparkz_alot - Dec-02-2017 The images look very clean and professional. Did you use wxPython for the GUI? RE: Enigma Machine, I need help! - Larz60+ - Dec-02-2017 I used tkinter. They are just overlays of the same image. I colored the centers with gimp. I'm trying to finish up this weekend. I had restarted the encryption routine about four times, each time believing that I really understood the operation. But not actually getting it right until two days ago. This time I did it correctly, building my test case first, so I'm confident (yet again) that I have it right this time. I'm also feeling guilty for commandeering the project. RE: Enigma Machine, I need help! - Larz60+ - Dec-04-2017 Hate to say I'm still working on this, but I am, at least I haven't given up, nor will I. I found several more on line emulators - In order of favorite to least favorite https://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-u_v20_en.html http://enigma.louisedade.co.uk/enigma.html http://summersidemakerspace.ca/projects/enigma-machine/ Key sheet generators: https://meinenigma.com/keychart.php http://enigma.louisedade.co.uk/dailykeys.html RE: Enigma Machine, I need help! - Kimkuq - Dec-06-2017 (Dec-04-2017, 01:49 AM)Larz60+ Wrote: Hate to say I'm still working on this, but I am, at least I haven't given up, nor will I. Hey again! I have to thank you a lot for sticking so much to this project!! It will serve me to be a great source of inspiration which I am looking very forward to! You do not have to stress for the time, as long as the program gets done sometime, I'll be happy (which I am very laready)! :D Just tell me, just in case something else come through, when you will give up (which I don't think you would) and stop thi project. And don't worry for commandeering around this proect, becasue what you have done so far, isn't even close to in reach for my skills at the moment. I can understand the code, and will only be able to copy the structure for the future! Thank you a lot!! RE: Enigma Machine, I need help! - Larz60+ - Dec-06-2017 you will get the engine very soon. there is a gui for plugboard which you can incorporate into your own gui, it is a class, and all you have to do to use it is instantiate the class, passing it the parent window. When done setting plugs, the pairs will be in an array which can be acessed by classname.plugboard_pairs The PlugBoard.py class is up to date on GitHub. I don't plan on changing it anymore, so you can start to use it if you wish. RE: Enigma Machine, I need help! - Larz60+ - Dec-07-2017 Here is a copy of Daniel Palloks browser enigma simulator that I converted to english (download and double click to activate) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Enigma I / M3 - Simulator by dp</title> <meta name="author" content="Daniel Palloks"> <meta name="version" content="v1.6 (30 Oct 2011)"> <meta name="generator" content="Notepad2"> <meta name="description" content="Enigma-Simulator in Javascript"> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> <script type="text/javascript"> // Enigmas I & M3: Roters I-VIII; Reversing Rollers A, B, C; ETW(I) // === Variablendeklarationen === // --- Feste Werte --- var abc = 'abcdefghijklmnopqrstuvwxyz'; // geordnetes Alphabet var walzeI = 'ekmflgdqvzntowyhxuspaibrcj'; // Walze I (Rotor) var walzeII = 'ajdksiruxblhwtmcqgznpyfvoe'; // Walze II (Rotor) var walzeIII = 'bdfhjlcprtxvznyeiwgakmusqo'; // Walze III (Rotor) var walzeIV = 'esovpzjayquirhxlnftgkdcmwb'; // Walze IV (Rotor) var walzeV = 'vzbrgityupsdnhlxawmjqofeck'; // Walze V (Rotor) var walzeVI = 'jpgvoumfyqbenhzrdkasxlictw'; // Walze VI (Rotor) var walzeVII = 'nzjhgrcxmyswboufaivlpekqdt'; // Walze VII (Rotor) var walzeVIII = 'fkqhtlxocbjspdzramewniuygv'; // Walze VIII (Rotor) var ukb = 'yruhqsldpxngokmiebfzcwvjat'; // Umkehrwalze B (fest) var ukc = 'fvpjiaoyedrzxwgctkuqsbnmhl'; // Umkehrwalze C (fest) var uka = 'ejmzalyxvbwfcrquontspikhgd'; // Umkehrwalze A (fest) var et0 = abc; // Eintrittswalze (fest, keine Permutation) var notch = 'rfwkaaaa'; // Übertragskerben f. Weiterdrehung d. nächsten Walze var winfo = new Array ('Übertrag: ', 'Q|R','E|F','V|W','J|K','Z|A','Z|A, M|N','Z|A, M|N','Z|A, M|N'); var wname = new Array ('I','II','III','IV','V','VI','VII','VIII'); var oldqwertz = 'QWERTZUIOASDFGHJKPYXCVBNML'; // Enigma-Tastatur // --- Ende feste Werte --- // -- Auswahl + Defaults -- var ukw = ukb, etw = et0; // Auswahl UKW, ETW var walz01 = walzeI, walz02 = walzeII, walz03 = walzeIII; // 3 ausgewählte Walzen von 8: walz01: rechte (schnelle), walz02: mittlere, walz03: linke (Grundstellung, f. Reset) var walz1 = walz01, walz2 = walz02, walz3 = walz03; // innere Verdrahtung (f. Ringeinst.) var wlz1 = walz1, wlz2 = walz2, wlz3 = walz3; // 3 Walzen zum Stellen (Startwerte) var n1 = abc.indexOf(notch.charAt(0)), n2 = abc.indexOf(notch.charAt(1)); // Kerben der zwei rechten gewählten Rotoren var n11 = n1, n21 = n2; // Zweite Kerbe (gleich erste K. gesetzt) var w1set = 65, w2set = 65, w3set = 65; // Walzenstellung 'A' (real) var w1out = 65, w2out = 65, w3out = 65; // Walzenstellung 'A' (angezeigt) var r1set = 0, r2set = 0, r3set = 0; // Ringstellung '1' var kcheck = ''; // Steckerpaare var swp = abc, gesteckert = false; // Steckerkonfiguration var ringst = false; // Modus 'Ringstellung' aus var qwertzu = false; // QWERTZU-Tastatur aus var monitor = false; // - Initialisierung dynamische Werte - var w1 = wlz1, w2 = wlz2, w3 = wlz3; // Momentaufnahme der rotierten Walzen var lastkey = -1; // f. QWERTZ-Anzeige var coded = 0; // Anzahl kodierter Zeichen var reset1 = true, reset2 = true, reset3 = true; // f. input box-Rolling lock, s. set() // === Ende Variablendeklarationen === // ====== Funktionen ====== function info() { alert('\tEnigma I & M3 Emulator '+document.getElementsByName("version")[0].content+'\n\t(c) 2007-2011 Daniel Palloks\n\nInfos: http:\/\/people.physik.hu-berlin.de\/~palloks\/js\/enigma\/\n\nDas Programm ist Freeware und darf nach Belieben weitergegeben und verändert werden, solange (1) meine Urheberschaft anerkannt bleibt, (2) alle Änderungen entsprechend gekennzeichnet werden, (3) der Freeware-Status und die Bedingungen für Weitergabe/Änderungen gewahrt bleiben. Dies gilt auch für Teile des Quelltextes, sofern sie an anderer Stelle verwendet werden. Bei der Weitergabe der Software muß auch eine Kopie dieser Bestimmungen weitergegeben werden. -- Der Autor haftet nicht für Schäden, die mittelbar oder unmittelbar durch die Benutzung der Software entstehen.'); } function neu() { // Wenn Reload-Button d. Browsers betätigt... document.f.reset(); //leert Formular m. Walzeneinstellungen + Walzenauswahl wlzReset(); rngReset(); unsteck(); //Stecker bleiben, müssen aber neu aktiviert werden } function wlzReset() { wlz1 = walz1; wlz2 = walz2; wlz3 = walz3; //könnte noch Ringstellg. haben! w1 = wlz1; w2 = wlz2; w3 = wlz3; w1set = w2set = w3set = 65; // wenn weg --> Reset auf letzte man. Walzenstellg.! w1out = w2out = w3out = 65; reset1 = reset2 = reset3 = true; document.f.w1.value = String.fromCharCode(w1set); document.f.w2.value = String.fromCharCode(w2set); document.f.w3.value = String.fromCharCode(w3set); wlzAktuellShow(); viewKey(); } function rngReset() { walz1 = rot(walz1,r1set); walz2 = rot(walz2,r2set); walz3 = rot(walz3,r3set); //innere Verdrathg. zurückdrehen wlz1 = rot(wlz1,r1set); wlz2 = rot(wlz2,r2set); wlz3 = rot(wlz3,r3set); //Var. synchronisieren r1set = r2set = r3set = 0; document.f.r1.value = String(r1set +1); document.f.r2.value = String(r2set +1); document.f.r3.value = String(r3set +1); wlzStellShow(); viewKey(); } function steckReset () { stbMark() // nur Effekt swp = abc; kcheck= ''; for (var i=0; i<13; i++) document.getElementsByName('stf')[i].value= ''; setTimeout('steck()',150); } function unsteck() { swp = abc; kcheck= ''; stecker = false; viewKey(); // Stecker deaktivieren (nicht löschen) document.getElementById("stb").value = ' Activate '; for (var i=0; i<13; i++) { //Stecker vorhanden? Eingabeknopf markieren if (document.s.stf[i].value != '') { stbMark(); break } } } function wlzAktuellShow () { document.getElementById('walzen').innerHTML= wlz3+' '+wlz2+' '+wlz1+'<br>'+w3+' '+w2+' '+w1; } function wlzStellShow () { document.getElementById('walzen').innerHTML= walz3+' '+walz2+' '+walz1+'<br>'+wlz3+' '+wlz2+' '+wlz1; } function w3sel (sel) { w3set = w3out = 65; document.f.w3.value="A"; r3set = 0; document.f.r3.value="1"; wlz3 = walz3 = walz03 = wselect(sel); //w3 = wlz3; reset3 = true; document.getElementById('rng3').innerHTML= wname[sel-1]; wlzStellShow (); viewKey(); } function w2sel (sel) { w2set = w2out = 65; document.f.w2.value="A"; r2set = 0; document.f.r2.value="1"; wlz2 = walz2 = walz02 = wselect(sel); //w2 = wlz2; n2 = abc.indexOf(notch.charAt(parseInt(sel-1))); // passende Kerbe zuordnen! n21 = (sel > 5)? abc.indexOf('n') : n2; // VI-VIII haben Kerben bei M|N und Z|A! reset2 = true; document.getElementById('rng2').innerHTML= wname[sel-1]; wlzStellShow (); viewKey(); } function w1sel (sel) { w1set = w1out = 65; document.f.w1.value="A"; r1set = 0; document.f.r1.value="1"; wlz1 = walz1 = walz01 = wselect(sel); //w1 = wlz1; n1 = abc.indexOf(notch.charAt(parseInt(sel-1))); n11 = (sel > 5)? abc.indexOf('n') : n1; reset1 = true; document.getElementById('rng1').innerHTML= wname[sel-1]; wlzStellShow (); viewKey(); } function wselect (sel) { var w; switch(sel) { case "1": w = walzeI; break; case "2": w = walzeII; break; case "3": w = walzeIII; break; case "4": w = walzeIV; break; case "5": w = walzeV; break; case "6": w = walzeVI; break; case "7": w = walzeVII; break; case "8": w = walzeVIII; break; } return w; } function ukwlz(sel) { switch(sel) { case "A": ukw = uka; document.getElementById("ukw").style.color= "#000"; document.getElementById("ukw").style.backgroundColor= "#c0c0c0"; break; case "B": ukw = ukb; document.getElementById("ukw").style.color= "blue"; document.getElementById("ukw").style.backgroundColor= "#c0c0c0"; break; case "C": ukw = ukc; document.getElementById("ukw").style.color= "blue"; document.getElementById("ukw").style.backgroundColor= "#fff"; break; } viewKey(); } function set(s) { if (document.f.inp.value != '' && !(reset1 && reset2 && reset3)) return 0; // gesperrt var n = s.charCodeAt(0); if (n==43) return 1; if (n==45) return -1; if (n < 65 || n > 90 || s=='') return 0; return n; } function setr(s) { var n=0; if (!(isNaN(s))) { n = parseInt(s) +1; // Abgrenzen v. '+'-Taste mit Wert 1 (später wieder rückrechnen!) if (n==1) n=2; // Eingabe Null gleich Eingabe Eins (wird also hier 2) else if (n < 1 || n > 27 || s=='') n= 0; } return n; } function set3(n) { if (n==0) { if (ringst) document.f.r3.value = r3set +1; else document.f.w3.value = String.fromCharCode(w3out); return; } if (ringst) { if (n > 1 && n < 28) n -= r3set +2; // n aus rset() war ggü. r3set um 2 erhöht! r3set = (r3set + n) % 26; if (r3set < 0) r3set= 26 + n; document.f.r3.value = String(r3set + 1); walz3 = rot(walz3,-n); wlz3 =rot(wlz3,-n); } else { if (n > 64 && n < 91) n -= w3out; // Abstand neuer-alter Wert w3set = 65 + (w3set - 65 + n) % 26; if (w3set< 65) w3set= 91 + n; w3out = 65 + (w3out - 65 + n) % 26; if (w3out< 65) w3out= 91 + n; document.f.w3.value = String.fromCharCode(w3out); wlz3 = rot(wlz3,n); } document.getElementById('walzen').innerHTML= '<b>'+walz3+'<\/b> '+walz2+' '+walz1+'<br><b>'+wlz3+'<\/b> '+wlz2+' '+wlz1; document.getElementById('status2').innerHTML= w3set-65 +'-' +r3set; viewKey(); } function set2(n) { if (n==0) { if (ringst) document.f.r2.value = r2set +1; else document.f.w2.value = String.fromCharCode(w2out); return; } if (ringst) { if (n > 1 && n < 28) n -= r2set +2; r2set = (r2set + n) % 26; if (r2set < 0) r2set= 26 + n; document.f.r2.value = String(r2set + 1); walz2 = rot(walz2,-n); wlz2 =rot(wlz2,-n); } else { if (n > 64 && n < 91) n -= w2out; w2set = 65 + (w2set - 65 + n) % 26; if (w2set< 65) w2set= 91 + n; w2out = 65 + (w2out - 65 + n) % 26; if (w2out< 65) w2out= 91 + n; document.f.w2.value = String.fromCharCode(w2out); wlz2 = rot(wlz2,n); } document.getElementById('walzen').innerHTML= walz3+' <b>'+walz2+'<\/b> '+walz1+'<br>'+wlz3+' <b>'+wlz2+'<\/b> '+wlz1; document.getElementById('status2').innerHTML= w2set-65 +'-' +r2set; viewKey(); } function set1(n) { if (n==0) { if (ringst) document.f.r1.value = r1set +1; else document.f.w1.value = String.fromCharCode(w1out); return; } if (ringst) { if (n > 1 && n < 28) n -= r1set +2; r1set = (r1set + n) % 26; if (r1set < 0) r1set= 26 + n; document.f.r1.value = String(r1set + 1); walz1 = rot(walz1,-n); wlz1 =rot(wlz1,-n); } else { if (n > 64 && n < 91) n -= w1out; w1set = 65 + (w1set -65 + n) % 26; if (w1set< 65) w1set= 91 + n; w1out = 65 + (w1out -65 + n) % 26; if (w1out< 65) w1out= 91 + n; document.f.w1.value = String.fromCharCode(w1out); wlz1 = rot(wlz1,n); } document.getElementById('walzen').innerHTML= walz3+' '+walz2+' <b>'+walz1+'<\/b><br>'+wlz3+' '+wlz2+' <b>'+wlz1+'<\/b>'; document.getElementById('status2').innerHTML= w1set-65 +'-' +r1set; viewKey(); } function switchWlzSettings (sw) { if (sw == false) { ringst = true; document.getElementById("walz").style.display= "none"; document.getElementById("rngst").style.display= ""; wlzStellShow(); } else { ringst = false; document.getElementById("rngst").style.display= "none"; document.getElementById("walz").style.display= ""; wlzAktuellShow(); } } function walzenrot () { if (document.f.rotieren.checked == true) document.getElementById("walzenrot").innerHTML= 'Walzen rotieren'; else document.getElementById("walzenrot").innerHTML= '<span style=background-color:#c33> Walzen fixiert! <\/span>'; } function steck () { var stest0, stest1, k0, k1; kcheck= ''; swp = abc; for (var i=0; i<13; i++) { stest0 = document.getElementsByName('stf')[i].value.charAt(0).toLowerCase(); stest1 = document.getElementsByName('stf')[i].value.charAt(1).toLowerCase(); if (stest1 == stest0) { document.getElementsByName('stf')[i].value= ''; stest0 = stest1 = '' } // Validieren... if (stest0 != '') { if ((stest0.charCodeAt(0) < 97 || stest0.charCodeAt(0) > 122) || (stest1.charCodeAt(0) < 97 || stest1.charCodeAt(0) > 122) || stest1 == '') { alert('Fehler! (Feld '+String(i+1)+')'); kcheck=''; return(false); } // Validieren2: Doppelgänger suchen... if (kcheck.lastIndexOf(stest0) >= 0 || kcheck.lastIndexOf(stest1) >= 0 ) { alert('Fehler! Doppelter Wert (Feld '+String(i+1)+').'); kcheck=''; return(false); } else { kcheck = stest0 + stest1 + kcheck; // Swap-String bauen (m. Ersetzen-Fkt. srepl())... k0 = abc.indexOf(stest0), k1 = abc.indexOf(stest1); swp = srepl(swp,k0,stest1); swp = srepl(swp,k1,stest0); }//-if !='' } //-for } if (swp != abc) { gesteckert = true; document.getElementById("stb").value = ' Deactivate '; // Knopf umschalten } document.getElementById("stb").style.fontWeight = 'normal'; // Knopf zurücksetzen document.getElementById("stb").style.color = '#000'; viewKey(); } function srepl (s, nr, c) { if (nr==0) s = c + s.substring(1); else s = s.substring(0, nr) + c + s.substring(nr + 1); return(s); } function stbMark() { var s= document.getElementById("stb"); s.value= ' Activate '; s.style.fontWeight= 'bold'; s.style.color= '#a52a2a'; } function fadeSt () { if (document.k.stl.value=="Plug connector off") { document.getElementById('stecker').style.display= "none"; document.k.stl.value= "Plug connector On"; } else { document.getElementById('stecker').style.display= ""; document.k.stl.value= "Plug connector off"; } } function fadeInp() { // --> TXT document.f.out.value= ''; document.f.inp.value= ''; coded = 0; if (qwertzu) { // --> TXT qwertzu = false; document.getElementById("qwertzu").style.display = "none"; document.getElementById("txtfeld").style.display = ""; document.k.qw.value= "QWERTZU-Tastatur"; if (ringst) { ringst = false; var t = true } // folgende Zeile nur für Walzenpos. set1(w1set); set2(w2set); set3(w3set); // Zurück auf letzte man. Einstellung if (t) ringst = true; // Änderung aus vorletzter Zeile rückgängig machen } else { // --> QWERTZU qwertzu = true; document.getElementById("txtfeld").style.display= "none"; document.getElementById("qwertzu").style.display= ""; document.k.qw.value= "input box "; if (lastkey > -1) document.getElementsByName('kqw')[lastkey].style.color= 'gray'; enigma(' '); // Zurück auf letzte man. Einstellung } w1set = w1out; w2set = w2out; w3set = w3out; viewKey(); } function fade () { if (document.k.knopf.value==" Monitor aus ") { document.getElementById('monitor').style.display= "none"; document.k.knopf.value= " Monitor ein "; monitor = false; } else { document.getElementById('monitor').style.display= ""; document.k.knopf.value= " Monitor "; monitor = true; } } function ttw(s) { if (ringst) return ( '"' +abc.charAt(Number(s.toLowerCase()) -1).toUpperCase() +'"' ); else return ( '"' +String(abc.indexOf(s.toLowerCase()) +1) +'"' ); } function tts(s) { var s0= s.charAt(0), s1= s.charAt(1), n0= s0.charCodeAt(0), n1= s1.charCodeAt(0); if (s!='' && n0 > 64 && n0 < 91 && n1 > 64 && n1 < 91) return ( '"' +String(abc.indexOf(s0.toLowerCase()) +1) +'/' +String(abc.indexOf(s1.toLowerCase()) +1) +'"' ); else return (''); } function viewKey() { var rg1=String(r1set +1), rg2=String(r2set +1), rg3=String(r3set +1); rg1= (rg1.length==2)? rg1 : '0'+rg1; rg2= (rg2.length==2)? rg2 : '0'+rg2; rg3= (rg3.length==2)? rg3 : '0'+rg3; if (qwertzu) { w1set = w1out; w2set = w2out; w3set = w3out; // Im QWERTZU-Modus nach Walzenstellen: Startpos. auf aktuelle Werte } var wg = new Array ( String.fromCharCode(w3set), String.fromCharCode(w2set), String.fromCharCode(w1set) ); if (kcheck=='') kcheck = ' - -'; var k='Reflector: '; k += (ukw == ukb)? 'B. ' : (ukw == ukc)? 'C. ' : 'A. '; k+= document.getElementById("rng3").innerHTML +' '+ document.getElementById("rng2").innerHTML +' '+ document.getElementById("rng1").innerHTML +' (' +wg +') '; k+= 'ring position: '+rg3+' '+rg2+' '+rg1+' '; k+= 'Plugboard:'; for (var i=kcheck.length -2; i > -1; i-=2) { if (kcheck.charAt(i) != kcheck.charAt(i+1)) k+= ' ' + kcheck.substr(i,2).toUpperCase(); } document.getElementById('key1').innerHTML=k; } // ---- MAIN LOOP (input box) ---- function enigma(s) { // berechnet immer gesamten Text im Fenster! if (monitor) { document.getElementById('status0').innerHTML= '<font color=#cc3333>In Arbeit...<\/font>'; if (s.length > 999) { var c= confirm('Achtung: Langer Eingabetext!\nDas Deaktivieren des Statusmonitors kann den Vorgang erheblich beschleunigen.\n\'OK\', um trotzdem fortzufahren (Fenster schließt u.U. nicht sofort).'); if (c==false) { document.getElementById('status0').innerHTML= '<font color=#cc3333>Abbruch!<\/font>'; return ''; } } } var startzeit = new Date(); document.getElementById('signal').innerHTML = ''; w1out = w1set, w2out = w2set, w3out = w3set; // eingestellte Walzenpos. u. -anzeige w1 = wlz1; w2 = wlz2; w3 = wlz3; coded = 0; var out = ''; // ... Walzen + Output zurücksetzen, da jedesmal String von Anfang an kodiert wird! for (var i=0; i < s.length; i++) { if (s.charCodeAt(i) > 96 && s.charCodeAt(i) < 123) { reset1 = false; reset2 = false; reset3 = false; if (document.f.rotieren.checked == true) gear(); //Walzenvortrieb out = out + kodieren(s.charAt(i)); if ((coded+1) % 5 ==0) out += ' '; coded++; } if (monitor) document.getElementById('status1').innerHTML = s.charCodeAt(i); } //-for document.f.w3.value = String.fromCharCode(w3out); document.f.w2.value = String.fromCharCode(w2out); document.f.w1.value = String.fromCharCode(w1out); wlzAktuellShow(); document.getElementById('status0').innerHTML = '( OK )'; document.getElementById('status3').innerHTML = coded; var endzeit = new Date(); var zeit = endzeit.getTime() - startzeit.getTime(); document.getElementById('time').innerHTML = zeit/1000 + ' s'; return(out); } // ---- End main loop ---- function en2(s) { // QWERTZU Main Loop (text input)... document.getElementById('status0').innerHTML= '<font color=#cc3333>In Arbeit...<\/font>'; if (s.length > 1) var start = new Date(); var l = document.f.out.value.length; for (var i=0; i < s.length; i++) { if (lastkey > -1) document.getElementsByName('kqw')[lastkey].style.color= 'gray'; var e = en(s.charAt(i).toLowerCase()).toUpperCase(); if (e != '') { var taste = oldqwertz.indexOf(e); document.getElementsByName('kqw')[taste].style.color = '#cc0'; lastkey = taste; l++; document.f.out.value += e; if ((l+1) % 6 == 0) { document.f.out.value += ' '; l++ } } } document.f.inpqw.value = ''; document.getElementById('status0').innerHTML= '( OK )'; if (s.length > 1) { var ende = new Date(); var zeit = ende.getTime() - start.getTime(); document.getElementById('time').innerHTML = zeit/1000 +' s'; } } function en(s) { // QWERTZU Main Loop... document.getElementById('time').innerHTML= ''; w1 = wlz1; w2 = wlz2; w3 = wlz3; if (monitor) document.getElementById('status1').innerHTML = s.charCodeAt(0); if (s.charCodeAt(0) > 96 && s.charCodeAt(0) < 123) { if (document.f.rotieren.checked == true) gear(); // Walzenvortrieb var out = kodieren(s.charAt(0)); wlz1 = w1; wlz2 = w2; wlz3 = w3; // ... soll ja immer weitergehen coded++; if (monitor) document.getElementById('walzen').innerHTML= walz3+' '+walz2+' '+walz1+'<br>'+w3+' '+w2+' '+w1; document.f.w3.value = String.fromCharCode(w3out); document.f.w2.value = String.fromCharCode(w2out); document.f.w1.value = String.fromCharCode(w1out); document.getElementById('status1').innerHTML = s.charCodeAt(0); document.getElementById('status3').innerHTML = coded; return out; } //-validate charCode else return ''; } // Walzenvortrieb function gear() { w1 = rot(w1,1); w1out++; if (w1out > 90) w1out= 65; // Anzeige Walze 1 var w1c0 = w1.charAt(0); if ( w2.charAt(1) == walz2.charAt(n2) || w2.charAt(1) == walz2.charAt(n21) ) { //Übertrag 2-3 m. Doppelschritt od. bei Spezialfall (hat Priorität) w2 = rot(w2,1); w3 = rot(w3,1); w2out++; if (w2out > 90) w2out= 65; w3out++; if (w3out > 90) w3out= 65; } else if (w1c0 == walz1.charAt(n1) || w1c0 == walz1.charAt(n11)) { // Übertrag 1-2 w2 = rot(w2,1); w2out++; if (w2out > 90) w2out= 65; } } // HIER passiert das Wesentliche! function kodieren(s) { // eff. Rotationsstellg.: Abstand Walzenpos. von Grundpos. der Verdrahtung // d.h. <Abst. Walzenpos. v. Grundpos.> - <Abst. Verdrahtg. v. ihrer Grundpos.> var rw1 = w1out - 65 - r1set; if (rw1 < 0) rw1 += 26; var rw2 = w2out - 65 - r2set; if (rw2 < 0) rw2 += 26; var rw3 = w3out - 65 - r3set; if (rw3 < 0) rw3 += 26; if (monitor) document.getElementById('status2').innerHTML= rw3+' '+rw2+' '+rw1; var s0 = (gesteckert)? swp.charAt(abc.indexOf(s)) : s; // Stecker am Eingang? var se = etw.charAt(abc.indexOf(s0)); //=s0; var s1 = w1.charAt(abc.indexOf(se)); // (ETW ist fest) var s2 = w2.charAt( (abc.indexOf(s1) - rw1 + 26) % 26 ); var s3 = w3.charAt( (abc.indexOf(s2) - rw2 + 26) % 26 ); var su = ukw.charAt( (abc.indexOf(s3) - rw3 + 26) % 26 ); var t = '<code>UKW W.3 W.2 W.1 ETW STK<br>'; t+=' ┌- '+s3+' <-- '+s2+' <-- '+s1+' <-- '+se+' <-- '+s0+' <-- '+s+' (REIN)<br> └> '+su; s3 = abc.charAt( w3.indexOf(abc.charAt((abc.indexOf(su) +rw3) % 26)) ); s2 = abc.charAt( w2.indexOf(abc.charAt((abc.indexOf(s3) +rw2) % 26)) ); s1 = abc.charAt( w1.indexOf(abc.charAt((abc.indexOf(s2) +rw1) % 26)) ); se = abc.charAt( etw.indexOf(s1) ); // = s1; s0 = (gesteckert)? swp.charAt(abc.indexOf(se)) : se; // Stecker am Ausgang? t= t+' --> '+s3+' --> '+s2+' --> '+s1+' --> '+se+' --> '+s0+' (RAUS)<\/code>' if (monitor) document.getElementById('signal').innerHTML= t; return s0; } function rot (w,n) { return (n>0)? w.substr(n)+ w.substr(0,n) : w.substr(w.length +n) + w.substring(0, w.length +n); } </script> <style type="text/css"> h3, form { margin-bottom: 0 } .rubrik { border:solid 1px #b9b8b6; background-color:#000; color:#fff; padding:5px; height:30px; text-align:center } .wlzbk { width:180px; border:solid 1px #b9b8b6; background-color:#c93; padding:5px } .wbk { background-color:#c0c0c0; text-align:center } .k a, .k a:visited { color:gray; font-weight:bold; text-decoration:none } .k a:hover { color:silver } .k a:active { font-size:12px; letter-spacing:2px } .i a, .i a:visited { color:yellow; text-decoration:none } .i a:hover { background-color:#333 } </style> <!--[if IE]><style type="text/css">h3 { margin: .2em 0 .5em }</style><![endif]--> </head> <!-- ====================================== --> <body onload="neu()"> <div align="center"> <noscript><h3 style="color:#a52a2a">Please activate Javascript!</h3></noscript> <table style="width:830px; border:solid 1px #000; padding:10px; background-color:#c93; background-image:url(enigma_logo_90px.gif); background-repeat:no-repeat; background-position: top center"> <tr><td colspan="5" style="text-align:center"><h3> Simulation of Enigma <span style="background-color:#c0c0c0;border:1px solid #000"> I </span><small> &</small> <span style="border:1px solid #000; color:blue"><span style="background-color:#c0c0c0"> M</span><span style="background-color:#fff">3 </span></span></h3></td></tr> <tr><td> <form name="f" action=""> <table width="100%" border="0"> <tr><td id="key1" colspan="5" style="height:25px; background-color:#c33; font-family:monospace; font-size:12px; border:solid 1px #000; text-align:center"> </td></tr> <tr><td class="rubrik" style="width:300px">I n p u t</td> <td class="rubrik" style="width:180px">R o l l e r s</td> <td class="rubrik" style="width:300px">O u t p u t</td> </tr> <tr><td id="txtfeld"> <textarea name="inp" title="Zum Einfügen Strg+V benutzen" rows="10" cols="35" style="border:solid 1px #b9b8b6; padding:5px; width:300px; height:180px; " onKeyUp="this.form.out.value=enigma(this.value.toLowerCase())" onDblClick="this.select()"></textarea></td> <td id="qwertzu" style="display:none"> <!-- QWERTZU-Feld --> <div class="k" style="width:300px; background-color:black; color:gray; font-family:Arial,sans-serif; font-size:16px"><div title="Virtuelle Tastatur" style="padding:20px; border:0px"> <a name="kqw" href="javascript:en2('Q')"> Q </a> <a name="kqw" href="javascript:en2('W')"> W </a> <a name="kqw" href="javascript:en2('E')"> E </a> <a name="kqw" href="javascript:en2('R')"> R </a> <a name="kqw" href="javascript:en2('T')"> T </a> <a name="kqw" href="javascript:en2('Z')"> Z </a> <a name="kqw" href="javascript:en2('U')"> U </a> <a name="kqw" href="javascript:en2('I')"> I </a> <a name="kqw" href="javascript:en2('O')"> O </a><br><br> <a name="kqw" href="javascript:en2('A')"> A </a> <a name="kqw" href="javascript:en2('S')"> S </a> <a name="kqw" href="javascript:en2('D')"> D </a> <a name="kqw" href="javascript:en2('F')"> F </a> <a name="kqw" href="javascript:en2('G')"> G </a> <a name="kqw" href="javascript:en2('H')"> H </a> <a name="kqw" href="javascript:en2('J')"> J </a> <a name="kqw" href="javascript:en2('K')"> K </a><br><br> <a name="kqw" href="javascript:en2('P')"> P </a> <a name="kqw" href="javascript:en2('Y')"> Y </a> <a name="kqw" href="javascript:en2('X')"> X </a> <a name="kqw" href="javascript:en2('C')"> C </a> <a name="kqw" href="javascript:en2('V')"> V </a> <a name="kqw" href="javascript:en2('B')"> B </a> <a name="kqw" href="javascript:en2('N')"> N </a> <a name="kqw" href="javascript:en2('M')"> M </a> <a name="kqw" href="javascript:en2('L')"> L </a><br><br> <span style="font-size:0.8em; color:#a52a2a; text-align:right">Click on buttons or enter here: <input type="text" name="inpqw" title="Einfügen mit Strg+V" size="1" style="text-align:center" onKeyUp="var s=this.value; this.value=''; en2(s);"></span> </div></div></td> <!-- Ende QWERTZU --> <td id="walz"> <table class="wlzbk"> <tr><td colspan="3" align="center"> [ <select id="ukw" size="1" style="text-align:center;font-family:serif;font-size:12px;background-color:#c0c0c0;color:blue" onChange="ukwlz(this.value)"> <option value="A">UKW: A</option> <option selected value="B">UKW: B</option> <option value="C">UKW: C</option> </select> ] </td> </tr> <tr><td class="wbk"><select name="s3" onMouseOver="this.title= winfo[0]+winfo[this.value]" size="1" style="text-align:center;font-family:serif;font-size:12px;color:blue;background-color:#c0c0c0" onChange="{this.style.backgroundColor=(Number(this.value)>5)?'#fff':'#c0c0c0'; w3sel(this.value)}"> <option value="1" onMouseOver="this.title=winfo[0]+winfo[1]">I</option> <option value="2" onMouseOver="this.title=winfo[0]+winfo[2]">II</option> <option selected value="3" onMouseOver="this.title=winfo[0]+winfo[3]">III</option> <option value="4" onMouseOver="this.title=winfo[0]+winfo[4]">IV</option> <option value="5" onMouseOver="this.title=winfo[0]+winfo[5]">V</option> <option value="6" onMouseOver="this.title=winfo[0]+winfo[6]">VI</option> <option value="7" onMouseOver="this.title=winfo[0]+winfo[7]">VII</option> <option value="8" onMouseOver="this.title=winfo[0]+winfo[8]">VIII</option> </select><br> <input type="button" value=" - " onClick="set3(set('-'))"><br><input type="text" name="w3" size="1" maxlength="1" value="A" style="text-align:center" onClick="this.select()" onKeyUp="this.value=this.value.toUpperCase(); set3(set(this.value))" onMouseOver="this.title=ttw(this.value)"><br><input type="button" value=" + " onClick="set3(set('+'))"></td> <td class="wbk"><select name="s2" onMouseOver="this.title= winfo[0]+winfo[this.value]" size="1" style="text-align:center;font-family:serif;font-size:12px;color:blue;background-color:#c0c0c0" onChange="{this.style.backgroundColor=(Number(this.value)>5)?'#fff':'#c0c0c0'; w2sel(this.value)}"> <option value="1" onMouseOver="this.title=winfo[0]+winfo[1]">I</option> <option selected value="2" onMouseOver="this.title=winfo[0]+winfo[2]">II</option> <option value="3" onMouseOver="this.title=winfo[0]+winfo[3]">III</option> <option value="4" onMouseOver="this.title=winfo[0]+winfo[4]">IV</option> <option value="5" onMouseOver="this.title=winfo[0]+winfo[5]">V</option> <option value="6" onMouseOver="this.title=winfo[0]+winfo[6]">VI</option> <option value="7" onMouseOver="this.title=winfo[0]+winfo[7]">VII</option> <option value="8" onMouseOver="this.title=winfo[0]+winfo[8]">VIII</option> </select><br> <input type="button" value=" - " onClick="set2(set('-'))"><br><input type="text" name="w2" size="1" maxlength="1" value="A" style="text-align:center" onClick="this.select()" onKeyUp="this.value=this.value.toUpperCase(); set2(set(this.value))" onMouseOver="this.title=ttw(this.value)"><br><input type="button" value=" + " onClick="set2(set('+'))"></td> <td class="wbk"><select name="s1" onMouseOver="this.title= winfo[0]+winfo[this.value]" size="1" style="text-align:center;font-family:serif;font-size:12px;color:blue;background-color:#c0c0c0" onChange="{this.style.backgroundColor=(Number(this.value)>5)?'#fff':'#c0c0c0'; w1sel(this.value)}"> <option selected value="1" onMouseOver="this.title=winfo[0]+winfo[1]">I</option> <option value="2" onMouseOver="this.title=winfo[0]+winfo[2]">II</option> <option value="3" onMouseOver="this.title=winfo[0]+winfo[3]">III</option> <option value="4" onMouseOver="this.title=winfo[0]+winfo[4]">IV</option> <option value="5" onMouseOver="this.title=winfo[0]+winfo[5]">V</option> <option value="6" onMouseOver="this.title=winfo[0]+winfo[6]">VI</option> <option value="7" onMouseOver="this.title=winfo[0]+winfo[7]">VII</option> <option value="8" onMouseOver="this.title=winfo[0]+winfo[8]">VIII</option> </select><br> <input type="button" value=" - " onClick="set1(set('-'))"><br><input type="text" name="w1" size="1" maxlength="1" value="A" style="text-align:center" onClick="this.select()" onKeyUp="this.value=this.value.toUpperCase(); set1(set(this.value))" onMouseOver="this.title=ttw(this.value)"><br><input type="button" value=" + " onClick="set1(set('+'))"></td> </tr> <tr><td colspan="3" align="center"><input type="checkbox" name="rotieren" checked="checked" onClick="walzenrot()"> <span id="walzenrot">Rotate rollers</span> </td> <tr><td colspan="3" align="center"><input type="button" name="resetknopf" onClick="wlzReset()" value=" NULL "> <input type="button" name="ringst" onClick="switchWlzSettings(false)" value="Rings »"></td> </tr> </table> </td> <!-- Ring settings --> <td id="rngst" style="display:none"> <table class="wlzbk"> <tr><td colspan="3" align="center" style="text-align:center"> R i n g S e t t i n g s:</td> </tr> <tr><td align="center" class="wbk"><span id="rng3">III</span><br><input type="button" value=" - " onClick="set3(-1)"><br><input type="text" name="r3" size="2" maxlength="2" value="1" style="text-align:center" onClick="this.select()" onKeyUp="set3(setr(this.value))" onMouseOver="this.title=ttw(this.value)"><br><input type="button" value=" + " onClick="set3(1)"></td> <td align="center" class="wbk"><span id="rng2">II</span><br><input type="button" value=" - " onClick="set2(-1)"><br><input type="text" name="r2" size="2" maxlength="2" value="1" style="text-align:center" onClick="this.select()" onKeyUp="set2(setr(this.value))" onMouseOver="this.title=ttw(this.value)"><br><input type="button" value=" + " onClick="set2(1)"></td> <td align="center" class="wbk"><span id="rng1">I</span><br><input type="button" value=" - " onClick="set1(-1)"><br><input type="text" name="r1" size="2" maxlength="2" value="1" style="text-align:center" onClick="this.select()" onKeyUp="set1(setr(this.value))" onMouseOver="this.title=ttw(this.value)"><br><input type="button" value=" + " onClick="set1(1)"></td> </tr> <tr><td colspan="3" align="center" ><input type="button" name="rreset" onClick="rngReset()" value=" Reset ring settings "></td></tr> <tr><td colspan="3" align="right"><input type="button" name="rueck" onClick="switchWlzSettings(true)" value=" « Roller Settings "> </td> </tr> </table> </td> <!-- End Ring settings --> <td> <textarea name="out" readonly="readonly" rows="10" cols="35" onMouseOver="this.title='Doppelklick: alles markieren';if (qwertzu) this.title+='. Zum Löschen Eingabemodus umschalten'" onDblClick="this.select()" style="border:solid 1px #b9b8b6;padding:5px;width:300px;height:180px"></textarea> </td></tr> </table> </form> </td></tr> <tr><td align="center"> <form name="k" action=""> <div><input type="button" name="qw" title="Eingabemodus umschalten" onClick="fadeInp()" value="Qwertzu keys"> <input type="button" name="stl" onClick="fadeSt()" value="Plug connector"> <input type="button" name="knopf" onClick="fade()" value=" Monitor"> <input type="button" name="neuladen" onClick="window.location.href=window.location.href" value="Reset all"></div> </form> </td></tr> <!-- Steckerleiste --> <tr id="stecker" style="display:none"><td> <form name="s" action=""> <table width="100%" border="0"> <tr><td colspan="3" class="rubrik" style="width:100%">C o n n e c t o r s t r i p ( e n t e r p a i r s o f l e t t e r s t o b e e x c h a n g e d ! )</td> </tr> <tr><td> <table style="width:100%; height:20px; border:solid 1px #b9b8b6;padding:0px; font-family:monospace; font-size:13px"> <tr style="text-align:center"> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td> </td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}" onMouseOver="this.title=tts(this.value)"></td> <td> </td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" style="background-color:#f0f0f0" onMouseOver="this.title=tts(this.value)" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" style="background-color:#f0f0f0" onMouseOver="this.title=tts(this.value)" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}"></td> <td><input type="text" name="stf" size="2" maxlength="2" onClick="this.select()" style="background-color:#f0f0f0" onMouseOver="this.title=tts(this.value)" onKeyUp="{this.value=this.value.toUpperCase();stbMark()}"></td> </tr> <tr><td colspan="15" align="center"><input type="button" id="stb" value=" Activate " onClick="{if (this.value==' Activate ') steck(); else unsteck();}"> <input type="button" value=" Clear all " onClick="steckReset()"> </td></tr> </table> </td></tr> </table> </form> </td></tr> <!-- Monitor --> <tr id="monitor" style="display:none"><td> <table style="width:100%; border:0px"> <tr><td class="rubrik" style="width:100%">M o n i t o r ( S i g n a l f l o w & R o t o r w i r i n g)</td> </tr> <tr><td> <table style="width:100%; height:200px; border:solid 1px #b9b8b6;padding:0px; font-family:monospace; font-size:13px; background-color:#fff"> <tr><td id="status0" style="width:29%; height:80px; text-align:center"></td> <td id="signal" style="width:44%"></td> <td id="time" style="width:27%; text-align:center"></td> </tr> <tr><td colspan="3" valign="baseline" style="height:10px; text-align:center; text-decoration:underline; color:#b0b0b0"> abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz</td> </tr> <tr><td id="walzen" colspan="3" align="center" valign="top"></td> </tr> <tr style="color:#b0b0b0; text-align:center"><td>last entry</td> <td>eff. Rotation (latest)</td> <td style="text-align:left">Coded characters</td> </tr> <tr><td id="status1" align="center"> </td> <td id="status2" align="center"> </td> <td id="status3" align="center"> </td> </tr> </table> </td></tr> </table> </td></tr> <!-- Fußzeile --> <tr><td> <table class="i" style="width:100%; border:0"> <tr><td class="rubrik" style="width:30px; height:20px"><small><a href="javascript:info()" title="Programm-Info"> i </a> | <a href="http://people.physik.hu-berlin.de/~palloks/js/enigma/" title="Übersichtsseite (online)"> ? </a></small></td> <td class="rubrik" style="height:20px; text-align:right"><small><em>© 2007-11 Daniel Palloks</em> </small> </td></tr> </table> </td></tr> </table> </div> </body> </html> RE: Enigma Machine, I need help! - Larz60+ - Dec-08-2017 Still struggling with this code. The fact is, and I hate to admit it, my mind just doesn't work right anymore. Ten years ago, I'd have done this in one evening. But it's slow now. I'm going to post my latest attempt, so any help would be appreciated. There are a lot of debugging printouts in this code that show exactly what's going on. The code seems to work perfectly for the right rotor, but not for the middle or left. The code should be pretty much the same for all three, except for the rotor advancement before the first rotor encryption. The setup for the test is (left to right): Rings: 12, 4, 8 Roller Window: Q, U, O PlugBoard: MZ, NS Rotors: V, III, II Reflector: B Message: Enigma ----------------------- The step by step operation should look like: [attachment=304] ------------------------ import EnigmaPaths import string import collections import json import copy class EncryptDammit: def __init__(self, plugboard_pairs, rotors, rings, rotor_window, reflector): self.rotors = rotors self.rings = rings self.rotor_window = rotor_window self.reflector = reflector self.epath = EnigmaPaths.EnigmaPaths() with self.epath.enigma_info.open() as f: self.init_data = json.load(f) # Set up ciphers for test, V, III, I (left to right) # Initial cipher shifted (ring setting - window letter index) = # 12 - abs((ord('O') - ord('A')))| = for right rotor test self.rotor_info = {} self.set_up_rotor_info() self.window_incr = [0, 0, 0] def set_up_rotor_info(self): # Set up ciphers for test, V, III, I (left to right) # Initial cipher shifted by self.rotor_info[side]['current_offset'] self.rotor_info['plugboard'] = {} self.rotor_info['plugboard']['cipher'] = collections.deque('ABCDEFGHIJKLZSOPQRNTUVWXYM') self.rotor_info['alpha'] = collections.deque(string.ascii_uppercase) self.rotor_info['reflector_cipher'] = collections.deque(self.init_data[f'reflector_{self.reflector}']) self.sides = {'left': 0, 'middle': 1, 'right': 2} # Keep three ciphers, one for ring offset, one for roller offset, one unmodified for side, side_idx in self.sides.items(): self.rotor_info[side] = {} self.rotor_info[side]['rotor'] = self.rotors[side_idx] self.rotor_info[side]['ring_offset'] = self.rings[side_idx] self.rotor_info[side]['roller_window'] = copy.deepcopy(self.rotor_window[side_idx]) self.rotor_info[side]['roller_window_offset'] = ord(self.rotor_info[side]['roller_window']) - ord('A') self.rotor_info[side]['alpha'] = collections.deque(string.ascii_uppercase) rotor_name = f"rotor{self.rotor_info[side]['rotor']}_info" self.rotor_info[side]['notch'] = self.init_data['rotor_info'][rotor_name]['notches'][0] self.rotor_info[side]['cipher'] = collections.deque(self.init_data['rotor_info'][rotor_name]['cipher']) # self.rotate_ring_cipher() # for side, side_idx in self.sides.items(): # self.rotate_roller_cipher(side, self.rotor_info[side]['roller_window_offset']) def rotate_ring_cipher(self): """ Rotate ring cipher (call once only) :return: None """ for side, side_idx in self.sides.items(): self.rotor_info[side]['ring_cipher'].rotate(-self.rotor_info[side]['ring_offset']) def next_letter(self, letter): """ Perpetual letter incrementor :param letter: :return: Next letter in alphabet, rotates to 'A' if input is 'Z' """ return chr(((ord(letter) - ord('A') + 1) % 26) + ord('A')) def incr_roller(self, side): letter = self.rotor_info[side]['roller_window'] = self.next_letter(self.rotor_info[side]['roller_window']) self.rotor_info[side]['roller_window_offset'] = ord(self.rotor_info[side]['roller_window']) - ord('A') return letter def rotate_roller(self, side): letter = self.incr_roller(side) if letter == self.rotor_info[side]['notch']: if side == 'right': letter = self.incr_roller('middle') if letter == self.rotor_info['middle']['notch']: letter = self.incr_roller('left') elif side == 'middle': letter = self.incr_roller('left') # def update_roller_windows(self, side): # self.rotor_info[side]['roller_window'] = self.rotor_info[side]['roller_cipher'][0] # self.rotor_info[side]['roller_window_offset'] = ord(self.rotor_info[side]['roller_cipher'][0]) - ord('A') def get_alpha_index(self, letter): return ord(letter) - ord('A') def show_current_settings(self): pass print(f"\nPlugBoard cipher:........ {self.rotor_info['plugboard']['cipher']}") for side in ('left', 'middle', 'right'): print(f"\n{side} rotor:................ {self.rotor_info[side]['rotor']}") print(f"{side} ring offset:.......... {self.rotor_info[side]['ring_offset']}") print(f"{side} roller window:........ {self.rotor_info[side]['roller_window']}") print(f"{side} roller window offset:. {self.rotor_info[side]['roller_window_offset']}") print(f"{side}_alpha:................ {self.rotor_info[side]['alpha']}") print(f"{side}_cipher.......:........ {self.rotor_info[side]['cipher']}") print(f"{side}_notch:................ {self.rotor_info[side]['notch']}") print(f"\nreflector_cipher:............ {self.rotor_info['reflector_cipher']}") # print(f"self.current_{side}_offset:.. {self.rotor_info[side]['current_offset']}") def plugboard_encrypt(self, letter): idx = self.get_alpha_index(letter) return self.rotor_info['plugboard']['cipher'][idx] def rotor_encrypt(self, side, inchar): # Values needed print(f'\nrotor_encrypt - side: {side} input character: {inchar}') ring_offset = self.rotor_info[side]['ring_offset'] cipher = self.rotor_info[side]['cipher'] alpha_index = (self.get_alpha_index(inchar) + ring_offset) % 26 # Alpha_char serves no purpose except for test aid alpha_char = self.rotor_info[side]['alpha'][alpha_index] cipher_char = cipher[alpha_index] print(f'add rotor {self.sides[side]} offset: alpha_index: {alpha_index}, alpha_char: {alpha_char}') print(f'rotor {self.sides[side]} from right: cipher_char: {cipher_char}') cipher_char_idx = (self.get_alpha_index(cipher_char) - (ring_offset + 1)) % 26 outchar = cipher[cipher_char_idx] print(f'subtract rotor {self.sides[side]} offset: cipher_char_idx: {cipher_char_idx}, outchar: {outchar}') print(f'{outchar} <-- {side} ring encrypt <-- {inchar}') return outchar def encrypt_forward(self, letter): # run through patchboard pbchar = self.plugboard_encrypt(letter) print(f'\nplugboard --> {letter}') self.rotate_roller('right') rightchar = self.rotor_encrypt('right', pbchar) middlechar = self.rotor_encrypt('middle', rightchar) leftchar = self.rotor_encrypt('left', middlechar) # iidx = self.rotor_info[side]['ring_offset'] + (self.get_alpha_index(tchar) % 26) # output_letter = self.rotor_info[side]['cipher'][iidx] # O # print(f'right output_letter: {output_letter}') # out_ltr_index = self.get_alpha_index(output_letter) # print(f'out_ltr_index: {out_ltr_index}') # rightchar = self.rotor_info[side]['cipher'][self.get_alpha_index(output_letter) - # (self.rotor_info[side]['ring_offset'] + 1)] # side = 'middle' # ochar = rightchar # iidx = self.rotor_info[side]['ring_offset'] + (self.get_alpha_index(rightchar) % 26) # output_letter = self.rotor_info[side]['cipher'][iidx] # O # middlechar = self.rotor_info[side]['cipher'][((self.get_alpha_index(output_letter) - # (self.rotor_info[side]['ring_offset'] + 1)) % 26)] # print(f'\n{middlechar} <-- middle ring encrypt <-- {ochar}') # # side = 'left' # ochar = middlechar # iidx = self.rotor_info[side]['ring_offset'] + (self.get_alpha_index(middlechar) % 26) # output_letter = self.rotor_info[side]['cipher'][iidx] # O # idx1 = self.get_alpha_index(output_letter) # stepn = ((self.rotor_info[side]['ring_offset'] + 1) % 26) # leftchar = self.rotor_info[side]['cipher'][(idx1 - stepn) % 26] # print(f'iidx: {iidx}, output_letter: {output_letter}, idx1: {idx1}, stepn: {stepn}') # leftchar = self.rotor_info[side]['cipher'][((self.get_alpha_index(output_letter) - # (self.rotor_info[side]['ring_offset'] + 1)) % 26)] # print(f'\n{leftchar} <-- middle ring encrypt <-- {ochar}') # Should have a T at this point # UKW W.3 W.2 W.1 ETW STK # ┌- t <-- s <-- o <-- e <-- e <-- e (REIN) # └> m --> y --> q --> g --> g --> g (RAUS) return 'A' def encrypt_message(self, message): for letter in message: self.show_current_settings() outchar = self.encrypt_forward(letter) if __name__ == '__main__': # message = 'ENIGMA' message = 'E' az = EncryptDammit(plugboard_pairs=[['M', 'Z'], ['N', 'S']], rotors=[5, 3, 1], rings=[12, 4, 8], rotor_window=['Q', 'U', 'O'], reflector='B') # az.show_current_settings() az.encrypt_message(message)EnigmaPaths.py from pathlib import Path class EnigmaPaths: def __init__(self): self.homepath = Path('.') self.datapath = self.homepath / 'data' self.imagepath = self.homepath / 'image' self.enigma_info = self.datapath / 'enigma_info.json' self.color_info = self.datapath / 'color_info.json' self.patchboard_image = self.imagepath / 'patchboard.ppm' |