└── Enigma_Machine ├── README.md ├── enigma.pl └── enigma_condensed.pl /Enigma_Machine/README.md: -------------------------------------------------------------------------------- 1 | # Enigma Machine 2 | 3 | ![alt text](http://i.imgur.com/hjOIrnt.png "Sample IO on Ubuntu 12.04") 4 | 5 | ## About the Enigma Machine 6 | 7 | The Enigma Machine is a device famously used in WWII by German forces to encrpyt messages. It worked by 8 | sending current through a series of "scrambled" rotors, and bouncing it from a reflection plate, in order 9 | to produce an output that could be mirrored and, in turn, decrypted. 10 | 11 | [Here](http://en.wikipedia.org/wiki/Enigma_machine) is more about the history of the machine. 12 | 13 | [Here](http://users.telenet.be/d.rijmenants/en/enigmatech.htm) are some of the more technical details of how the machine works. 14 | 15 | ## Project Scope: 16 | 17 | This particular script is based on the **M3 model**, which features rotors **I**, **II**, **III** and a **B Reflector**. 18 | I encourage to fork my code and make it open to other models, or for that fact, any model. 19 | This project was compiled in GNU prolog. 20 | 21 | ## Usage: 22 | 23 | The predicate that deploys the enigma machine is **enigma**, which has five arguments. 24 | 25 | `enigma([Input],[A,B,C],[[X,Y],[M,N]], Output).` 26 | 27 | The first argument is the **input string**, in the form a list. 28 | 29 | The second argument are the **three rings** for encryption. They are in the order they are encountered, 30 | which is Rotor III, Rotor II and then Rotor I. 31 | 32 | The third argument is a list of pairs that form the **plugboard**. 33 | 34 | the fourth argument is the **output**, which should always be a variable. 35 | 36 | ### Examples: 37 | 38 | ``` 39 | | ?- enigma([b,u,t,t,e,r,f,l,y],[t,h,q],[[a,c],[b,f]],O). 40 | 41 | O = [o,n,f,k,o,c,v,c,q] 42 | 43 | (4 ms) yes 44 | | ?- enigma([o,n,f,k,o,c,v,c,q],[t,h,q],[[a,c],[b,f]],O). 45 | 46 | O = [b,u,t,t,e,r,f,l,y] 47 | 48 | (8 ms) yes 49 | | ?- 50 | ``` 51 | 52 | ### Credit 53 | 54 | Thanks to the folks at [enigmaco.de](http://enigmaco.de/enigma/enigma.html) for their great visualization, which made this project go much smoother. 55 | -------------------------------------------------------------------------------- /Enigma_Machine/enigma.pl: -------------------------------------------------------------------------------- 1 | head([H|_],H). 2 | 3 | indexOf([Element|_], Element, 0):- !. 4 | indexOf([_|Tail], Element, Index):- 5 | indexOf(Tail, Element, Index1), 6 | !, 7 | Index is Index1+1. 8 | 9 | reflect(List, Char, RChar) :- 10 | indexOf(List,Char,Index), 11 | reverse(List,RList), 12 | indexOf(RList,RChar,Index). 13 | 14 | step([Head|Tail], TList) :- 15 | append(Tail, [Head], TList). 16 | 17 | 18 | turn(List,0,List) :- 19 | !. 20 | 21 | turn([H|T],X,R) :- 22 | X > 0, 23 | Y is X-1, 24 | append(T,[H], Nlist), 25 | turn(Nlist, Y, R). 26 | 27 | 28 | %Accumulator Length------------------------------------------------------- 29 | 30 | accLen([],A,A). 31 | 32 | accLen([_|T],A,L) :- 33 | Anew is A+1, 34 | accLen(T,Anew,L). 35 | 36 | len(List,Length) :- accLen(List,0,Length). 37 | 38 | 39 | %Finding character from index--------------------------------------------- 40 | 41 | indexInList(List,Char,Index) :- 42 | len(List,L), 43 | Index < L, 44 | accIndex(List,Char,0,Index). 45 | 46 | accIndex([H|_],H,Index,Index) :- 47 | !. 48 | 49 | accIndex([_|T],Char,Place,Index) :- 50 | Place < Index, 51 | NPlace is Place+1, 52 | accIndex(T,Char,NPlace,Index). 53 | 54 | accIndex([],-1,_,_). 55 | 56 | 57 | %Single accumulator swap-------------------------------------------------- 58 | 59 | accFinish(T,Build,Out) :- 60 | append(Build,T,Fin), 61 | accSwap1([],_,_,Fin,Out). 62 | 63 | accSwap1([],_,_,Out,Out). 64 | 65 | accSwap1([H|T],Item1,Item2,Build,Out) :- 66 | len([H|T],L), 67 | L>0, 68 | (H = Item1 -> append(Build,[Item2],NBuild); 69 | append(Build,[H],NBuild)), 70 | (\+ member(Item1,T) -> accFinish(T,NBuild,Out); 71 | accSwap1(T,Item1,Item2,NBuild,Out)). 72 | 73 | sswap(List,Item1,Item2,Out) :- 74 | accSwap1(List,Item1,Item2,[],Out). 75 | 76 | 77 | %Double accumulator swap-------------------------------------------------- 78 | 79 | accSwap2([],_,_,Out,Out). 80 | 81 | accSwap2([H|T],Item1,Item2,Build,Out) :- 82 | len([H|T],L), L>0, 83 | (H = Item1 -> append(Build,[Item2],NBuild); 84 | (H = Item2 -> append(Build,[Item1],NBuild); 85 | append(Build,[H],NBuild))), 86 | (\+ member(Item1,T) -> accSwap1(T,Item2,Item1,NBuild,Out); 87 | (\+ member(Item2,T) -> accSwap1(T,Item1,Item2,NBuild,Out); 88 | accSwap2(T,Item1,Item2,NBuild,Out))). 89 | 90 | dswap(List,Item1,Item2,Out) :- 91 | accSwap2(List,Item1,Item2,[],Out). 92 | 93 | %Plugboard generation----------------------------------------------------- 94 | 95 | plugGen(Out,[],Out) :- 96 | !. 97 | 98 | 99 | plugGen(Board,[[A,B]|T],Out) :- 100 | dswap(Board,A,B,NBoard), 101 | plugGen(NBoard,T,Out). 102 | 103 | %List transition---------------------------------------------------------- 104 | 105 | transition(List1,List2,I,O) :- 106 | indexOf(List1,I,Index), 107 | indexInList(List2,O,Index). 108 | 109 | %Predefined cogs---------------------------------------------------------- 110 | 111 | alphabet([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z]). 112 | cogIII([b,d,f,h,j,l,c,p,r,t,x,v,z,n,y,e,i,w,g,a,k,m,u,s,q,o]). 113 | cogII([a,j,d,k,s,i,r,u,x,b,l,h,w,t,m,c,q,g,z,n,p,y,f,v,o,e]). 114 | cogI([e,k,m,f,l,g,d,q,v,z,n,t,o,w,y,h,x,u,s,p,a,i,b,r,c,j]). 115 | reflector([y,r,u,h,q,s,l,d,p,x,n,g,o,k,m,i,e,b,f,z,c,w,v,j,a,t]). 116 | 117 | 118 | 119 | %Master Enigma launcher 120 | %------------------------------------------------------------------------------ 121 | 122 | enigma(Input,[RIII,RII,RI],Pairs,Output) :- 123 | alphabet(A), 124 | plugGen(A,Pairs,Plugboard), 125 | m3(Input,[RIII,RII,RI],Plugboard,[],Output). 126 | 127 | %============================================================================== 128 | 129 | m3([],[_,_,_], _, O, O) :- 130 | !. 131 | 132 | m3( [Input|Rest], [RIII,RII,RI], Plugboard, Output, Final) :- 133 | 134 | %Initialize all parts---------------------------------------------------------- 135 | alphabet(Alphabet), 136 | 137 | alphabet(IIIs), 138 | cogIII(IIIe), 139 | 140 | alphabet(IIs), 141 | cogII(CogII), 142 | 143 | alphabet(Is), 144 | cogI(CogI), 145 | 146 | reflector(Reflector), 147 | 148 | %Apply changes----------------------------------------------------------------- 149 | 150 | %Turn cogIII appropriately 151 | indexOf(IIIs,RIII,IIIt), 152 | turn(IIIs,IIIt,CogIIIs), 153 | turn(IIIe,IIIt,CogIII), 154 | 155 | %Turn cogII appropriately 156 | indexOf(IIs,RII,IIt), 157 | turn(IIs,IIt,CogIIs), 158 | 159 | %Turn cogI appropriately 160 | indexOf(Is,RI,It), 161 | turn(Is,It,CogIs), 162 | 163 | %Alphabet -> Plugboard 164 | transition(Alphabet,Plugboard,Input,PInput), 165 | 166 | 167 | 168 | %CogIII------------------------------------------------------------------------ 169 | step(CogIIIs,CogIIIss), 170 | step(CogIII, CogIIIn), 171 | 172 | %input->initial_cog_step (OCogIIIs) 173 | transition(Alphabet,CogIIIss,PInput,OCogIIIs), 174 | 175 | %initial_cog_step -> cog_encryption (OCogIII) 176 | transition(CogIIIss,CogIIIn, OCogIIIs,OCogIII), 177 | 178 | 179 | %if the head of CogIIIss is a 'w' 180 | head(CogIIIss,H1), 181 | head(CogIIs,H2), 182 | (H1=w -> turn(CogIIs,1,CogIIss); 183 | (H2=e -> turn(CogIIs,1,CogIIss); 184 | %Added extra case for rotor2 185 | turn(CogIIs,0,CogIIss))), 186 | 187 | (H2=e -> turn(CogIs,1,CogIss); 188 | turn(CogIs,0,CogIss)), 189 | 190 | %cog_encryption -> input (EndCogIII) 191 | transition(CogIIIss,CogIIss,OCogIII,EndCogIII), 192 | 193 | %CogII------------------------------------------------------------------------- 194 | 195 | %initial_cog_step -> cog_encryption (OCogII) 196 | transition(Alphabet,CogII,EndCogIII,OCogII), 197 | 198 | %cog_encryption -> input (EndCogII) 199 | transition(CogIIss,CogIss,OCogII,EndCogII), 200 | 201 | %CogI-------------------------------------------------------------------------- 202 | 203 | %initial_cog_step -> cog_encryption (OCogI) 204 | transition(Alphabet,CogI,EndCogII,EndCogI), 205 | 206 | %% %Reflector------------------------------------------------------------------ 207 | 208 | transition(CogIss,Alphabet,EndCogI,InReflector), 209 | 210 | %Reflector -> EndReflector 211 | transition(Alphabet,Reflector,InReflector,EndReflector), 212 | 213 | transition(Alphabet,CogIss, EndReflector, BCogI), 214 | 215 | %CogI-------------------------------------------------------------------------- 216 | 217 | transition(CogI,Alphabet,BCogI,RCogI), 218 | 219 | %CogII 220 | %------------------------------------------------------------------------------ 221 | 222 | transition(CogIss,CogIIss,RCogI,InCogII), 223 | 224 | transition(CogII,Alphabet,InCogII,RCogII), 225 | 226 | %CogIII 227 | %------------------------------------------------------------------------------ 228 | 229 | transition(CogIIss,CogIIIss,RCogII,InCogIII), 230 | 231 | transition(CogIIIn, CogIIIss,InCogIII,RCogIII), 232 | 233 | %Output------------------------------------------------------------------------ 234 | transition(CogIIIss,Alphabet,RCogIII,POut), 235 | 236 | transition(Plugboard,Alphabet,POut,Out), 237 | 238 | append(Output,[Out],Build), 239 | 240 | head(CogIIIss,NRIII), 241 | head(CogIIss,NRII), 242 | head(CogIss,NRI), 243 | 244 | m3(Rest,[NRIII,NRII,NRI], Plugboard, Build, Final). 245 | 246 | 247 | %**************************************************************************************** 248 | %**************************************************************************************** 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /Enigma_Machine/enigma_condensed.pl: -------------------------------------------------------------------------------- 1 | head([H|_],H). 2 | indexOf([Element|_], Element, 0):- !. 3 | indexOf([_|Tail], Element, Index):- 4 | indexOf(Tail, Element, Index1), 5 | !, 6 | Index is Index1+1. 7 | reflect(List, Char, RChar) :- 8 | indexOf(List,Char,Index), 9 | reverse(List,RList), 10 | indexOf(RList,RChar,Index). 11 | step([Head|Tail], TList) :- 12 | append(Tail, [Head], TList). 13 | turn(List,0,List) :- 14 | !. 15 | turn([H|T],X,R) :- 16 | X > 0, 17 | Y is X-1, 18 | append(T,[H], Nlist), 19 | turn(Nlist, Y, R). 20 | accLen([],A,A). 21 | accLen([_|T],A,L) :- 22 | Anew is A+1, 23 | accLen(T,Anew,L). 24 | len(List,Length) :- accLen(List,0,Length). 25 | indexInList(List,Char,Index) :- 26 | len(List,L), 27 | Index < L, 28 | accIndex(List,Char,0,Index). 29 | accIndex([H|_],H,Index,Index) :- 30 | !. 31 | accIndex([_|T],Char,Place,Index) :- 32 | Place < Index, 33 | NPlace is Place+1, 34 | accIndex(T,Char,NPlace,Index). 35 | accIndex([],-1,_,_). 36 | accFinish(T,Build,Out) :- 37 | append(Build,T,Fin), 38 | accSwap1([],_,_,Fin,Out). 39 | accSwap1([],_,_,Out,Out). 40 | accSwap1([H|T],Item1,Item2,Build,Out) :- 41 | len([H|T],L), 42 | L>0, 43 | (H = Item1 -> append(Build,[Item2],NBuild); 44 | append(Build,[H],NBuild)), 45 | (\+ member(Item1,T) -> accFinish(T,NBuild,Out); 46 | accSwap1(T,Item1,Item2,NBuild,Out)). 47 | sswap(List,Item1,Item2,Out) :- 48 | accSwap1(List,Item1,Item2,[],Out). 49 | accSwap2([],_,_,Out,Out). 50 | accSwap2([H|T],Item1,Item2,Build,Out) :- 51 | len([H|T],L), L>0, 52 | (H = Item1 -> append(Build,[Item2],NBuild); 53 | (H = Item2 -> append(Build,[Item1],NBuild); 54 | append(Build,[H],NBuild))), 55 | (\+ member(Item1,T) -> accSwap1(T,Item2,Item1,NBuild,Out); 56 | (\+ member(Item2,T) -> accSwap1(T,Item1,Item2,NBuild,Out); 57 | accSwap2(T,Item1,Item2,NBuild,Out))). 58 | dswap(List,Item1,Item2,Out) :- 59 | accSwap2(List,Item1,Item2,[],Out). 60 | plugGen(Out,[],Out) :- !. 61 | plugGen(Board,[[A,B]|T],Out) :- 62 | dswap(Board,A,B,NBoard), 63 | plugGen(NBoard,T,Out). 64 | 65 | transition(List1,List2,I,O) :- 66 | indexOf(List1,I,Index), 67 | indexInList(List2,O,Index). 68 | alphabet([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z]). 69 | cogIII([b,d,f,h,j,l,c,p,r,t,x,v,z,n,y,e,i,w,g,a,k,m,u,s,q,o]). 70 | cogII([a,j,d,k,s,i,r,u,x,b,l,h,w,t,m,c,q,g,z,n,p,y,f,v,o,e]). 71 | cogI([e,k,m,f,l,g,d,q,v,z,n,t,o,w,y,h,x,u,s,p,a,i,b,r,c,j]). 72 | reflector([y,r,u,h,q,s,l,d,p,x,n,g,o,k,m,i,e,b,f,z,c,w,v,j,a,t]). 73 | enigma(Input,[RIII,RII,RI],Pairs,Output) :- 74 | alphabet(A), 75 | plugGen(A,Pairs,Plugboard), 76 | m3(Input,[RIII,RII,RI],Plugboard,[],Output). 77 | m3([],[_,_,_], _, O, O) :- !. 78 | m3( [Input|Rest], [RIII,RII,RI], Plugboard, Output, Final) :- 79 | alphabet(Alphabet), 80 | alphabet(IIIs), 81 | cogIII(IIIe), 82 | alphabet(IIs), 83 | cogII(CogII), 84 | alphabet(Is), 85 | cogI(CogI), 86 | reflector(Reflector), 87 | indexOf(IIIs,RIII,IIIt), 88 | turn(IIIs,IIIt,CogIIIs), 89 | turn(IIIe,IIIt,CogIII), 90 | indexOf(IIs,RII,IIt), 91 | turn(IIs,IIt,CogIIs), 92 | indexOf(Is,RI,It), 93 | turn(Is,It,CogIs), 94 | transition(Alphabet,Plugboard,Input,PInput), 95 | step(CogIIIs,CogIIIss), 96 | step(CogIII, CogIIIn), 97 | transition(Alphabet,CogIIIss,PInput,OCogIIIs), 98 | transition(CogIIIss,CogIIIn, OCogIIIs,OCogIII), 99 | head(CogIIIss,H1), 100 | head(CogIIs,H2), 101 | (H1=w -> turn(CogIIs,1,CogIIss); 102 | (H2=e -> turn(CogIIs,1,CogIIss); 103 | %Added extra case for rotor2 104 | turn(CogIIs,0,CogIIss))), 105 | 106 | (H2=e -> turn(CogIs,1,CogIss); 107 | turn(CogIs,0,CogIss)), 108 | transition(CogIIIss,CogIIss,OCogIII,EndCogIII), 109 | transition(Alphabet,CogII,EndCogIII,OCogII), 110 | transition(CogIIss,CogIss,OCogII,EndCogII), 111 | transition(Alphabet,CogI,EndCogII,EndCogI), 112 | transition(CogIss,Alphabet,EndCogI,InReflector), 113 | transition(Alphabet,Reflector,InReflector,EndReflector), 114 | transition(Alphabet,CogIss, EndReflector, BCogI), 115 | transition(CogI,Alphabet,BCogI,RCogI), 116 | transition(CogIss,CogIIss,RCogI,InCogII), 117 | transition(CogII,Alphabet,InCogII,RCogII), 118 | transition(CogIIss,CogIIIss,RCogII,InCogIII), 119 | transition(CogIIIn, CogIIIss,InCogIII,RCogIII), 120 | transition(CogIIIss,Alphabet,RCogIII,POut), 121 | transition(Plugboard,Alphabet,POut,Out), 122 | append(Output,[Out],Build), 123 | head(CogIIIss,NRIII), 124 | head(CogIIss,NRII), 125 | head(CogIss,NRI), 126 | m3(Rest,[NRIII,NRII,NRI], Plugboard, Build, Final). --------------------------------------------------------------------------------