Enigma 加密流程:
明文 -> Plug Board -> Rotor 1 -> Rotor 2 -> Rotor 3 -> Reflector | Plug Board <- Rotor 1 <- Rotor 2 <- Rotor 3
前提 Enigma 机需要从五个转子(Rotor)中挑3个进行工作,每个转子就是一个密码表,每加密一个字符转子就会转动,所以说 Enigma 机就像一个不断更新密码表的多表密码加密机器。
所以我们需要提前设定:
选择的转子 Rotor
每个转子的起始转动位置 Ring_Setting
当前转子的位置 Message_Key
Plug_Board(接线板) 更改 2 个字母直接的顺序。比如我们将 AB 相连,则输入A输出的就是B。在二战后期德军把接线板的可以更改的字符对数提升到10个。其实这个接线板就是起到我们说的“混淆”作用。
比如我们设置PO LM IU JK NH YT GB VF RE DC
1 2 3 4 char plug[27 ] ="AGDCRVBNUKJMLHPOQESYIFWXTZ" ; char input = 'D' ;char output = plug[input-'A' ];
Rotor(转子) 1 2 3 4 5 6 7 8 9 char rotor_table[5 ][27 ] = { "EKMFLGDQVZNTOWYHXUSPAIBRCJ" , "AJDKSIRUXBLHWTMCQGZNPYFVOE" , "BDFHJLCPRTXVZNYEIWGAKMUSQO" , "ESOVPZJAYQUIRHXLNFTGKDCMWB" , "VZBRGITYUPSDNHLXAWMJQOFECK" };
这个是五个转子对应的转换表。
明文通过 Plug_Board以后得到的字母要做以下运算:
1 2 3 char c = 'A' ;int delta = MessageKey-RingSetting;c = ((c-'A' )+delta+26 )%26 + 'A' ;
其中MessageKey在按键按下,也就是字母进来之前就要转动。每加密一个字符最右侧的转子就要转一格。这里还有一个特殊的转动规则:当转子转到临转位置时,将会带动左边的转子转动。
1 2 char step_char[6 ] = "RFWKA" ;
如果我们选择转子是123,当2处于E,3处于V时,加密下一个字符三个转子都要动一圈,这被称为double step
。
Reflector(反射板) 没什么好说的就是一个字符替换
1 2 char reflector[] = "YRUHQSLDPXNGOKMIEBFZCWVJAT" ;
详细说明加密过程 加密设置
1 2 3 4 5 Plug_Board : PO LM IU JK NH YT GB VF RE DC Rotor : 125 Ring_Setting : TIP Message_Key : CRY input : C
先过Plug_Board
1 2 3 char plug[27 ] ="AGDCRVBNUKJMLHPOQESYIFWXTZ" ;
然后按 5->2->1
的顺序依次过转子
1 output = rotor_table[x][input-'A' ]
1 2 3 4 5 6 char rotor_table[5 ] = "VZBRGITYUPSDNHLXAWMJQOFECK"
1 2 3 4 5 6 char rotor_table[2 ] = "AJDKSIRUXBLHWTMCQGZNPYFVOE"
1 2 3 4 5 6 char rotor_table[1 ] = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"
再过reflector
1 2 3 char reflector[] = "YRUHQSLDPXNGOKMIEBFZCWVJAT" ;
然后再按1->2->5
的顺序反差表
1 2 3 4 5 6 7 8 for (int i=0 ; i<26 ; ++i){ if (input == rotor_table[x][i]) { output = i + 'A' ; break ; } }
1 2 3 4 5 6 char rotor_table[1 ] = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"
1 2 3 4 5 6 char rotor_table[2 ] = "AJDKSIRUXBLHWTMCQGZNPYFVOE"
1 2 3 4 5 6 char rotor_table[5 ] = "VZBRGITYUPSDNHLXAWMJQOFECK"
最后再过一次Plug_Board
,这里也需反查
1 2 3 char plug[27 ] ="AGDCRVBNUKJMLHPOQESYIFWXTZ" ;
可以发现Enigma的加密过程十分对称,所以只要初始设定一致,把密文输入就是解密过程了。
源代码(C) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 #include <iostream> using namespace std ;char reflector[] = "YRUHQSLDPXNGOKMIEBFZCWVJAT" ; char rotor_table[5 ][27 ] = { "EKMFLGDQVZNTOWYHXUSPAIBRCJ" , "AJDKSIRUXBLHWTMCQGZNPYFVOE" , "BDFHJLCPRTXVZNYEIWGAKMUSQO" , "ESOVPZJAYQUIRHXLNFTGKDCMWB" , "VZBRGITYUPSDNHLXAWMJQOFECK" }; char step_char[6 ] = "RFWKA" ; string Enigma (int num_rotor[], char Ring_Setting[], char Message_Key[], char plug_board[], string input) ;int main () { int num_rotor[3 ]; char Ring_Setting[3 ], Message_Key[3 ], plug_board[27 ]="ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; string pb, input_text, output_text; cout << "Plugboard : " ; for (int i=0 ; i<10 ; i++) { cin >> pb; plug_board[pb[0 ]-'A' ] = pb[1 ]; plug_board[pb[1 ]-'A' ] = pb[0 ]; } cout << "Rotor (e.g. 1 2 3) : " ; for (int i=0 ; i<3 ; i++) cin >> num_rotor[i]; cout << "RingSetting (e.g. A B C) : " ; for (int i=0 ; i<3 ; i++) cin >> Ring_Setting[i]; cout << "MessageKey (e.g. A B C) : " ; for (int i=0 ; i<3 ; i++) cin >> Message_Key[i]; cout << "Input text : " << endl ; cin >> input_text; output_text = Enigma(num_rotor, Ring_Setting, Message_Key, plug_board, input_text); cout << "----------- result -----------" << endl ; cout << output_text << endl ; } string Enigma (int num_rotor[], char Ring_Setting[], \ char Message_Key[], char plug_board[], string input) { string res = "" ; for (int i=0 ; i<input.length(); i++) { char after_pb = plug_board[input[i]-'A' ]; int bug_flag = 1 ; if ((Message_Key[1 ]-'A' +1 )%26 +'A' == step_char[num_rotor[1 ]-1 ]) { Message_Key[0 ] = (Message_Key[0 ] - 'A' + 1 ) % 26 + 'A' ; Message_Key[1 ] = (Message_Key[1 ] - 'A' + 1 ) % 26 + 'A' ; bug_flag = 0 ; } if ((Message_Key[2 ]-'A' +1 )%26 +'A' == step_char[num_rotor[2 ]-1 ]) { if (bug_flag) Message_Key[1 ] = (Message_Key[1 ] -'A' + 1 ) % 26 + 'A' ; } Message_Key[2 ] = (Message_Key[2 ] - 'A' + 1 ) % 26 + 'A' ; int delta = Message_Key[2 ] - Ring_Setting[2 ]; char rotor_in = ((after_pb - 'A' ) + delta + 26 ) % 26 + 'A' ; char rotor_out = rotor_table[num_rotor[2 ]-1 ][rotor_in-'A' ]; rotor_out = ((rotor_out - 'A' ) - delta + 26 ) % 26 + 'A' ; delta = Message_Key[1 ] - Ring_Setting[1 ]; rotor_in = ((rotor_out - 'A' ) + delta + 26 ) % 26 + 'A' ; rotor_out = rotor_table[num_rotor[1 ]-1 ][rotor_in-'A' ]; rotor_out = ((rotor_out - 'A' ) - delta + 26 ) % 26 + 'A' ; delta = Message_Key[0 ] - Ring_Setting[0 ]; rotor_in = ((rotor_out - 'A' ) + delta + 26 ) % 26 + 'A' ; rotor_out = rotor_table[num_rotor[0 ]-1 ][rotor_in-'A' ]; rotor_out = ((rotor_out - 'A' ) - delta + 26 ) % 26 + 'A' ; char ref_out = reflector[rotor_out - 'A' ]; delta = Message_Key[0 ] - Ring_Setting[0 ]; ref_out = ((ref_out - 'A' ) + delta + 26 ) % 26 + 'A' ; for (int j=0 ; j<26 ; j++) if (ref_out == rotor_table[num_rotor[0 ]-1 ][j]) { rotor_out = 'A' + j; break ; } rotor_out = ((rotor_out - 'A' ) - delta + 26 ) % 26 + 'A' ; delta = Message_Key[1 ] - Ring_Setting[1 ]; rotor_out = ((rotor_out - 'A' ) + delta + 26 ) % 26 + 'A' ; for (int j=0 ; j<26 ; j++) if (rotor_out == rotor_table[num_rotor[1 ]-1 ][j]) { rotor_out = 'A' + j; break ; } rotor_out = ((rotor_out - 'A' ) - delta + 26 ) % 26 + 'A' ; delta = Message_Key[2 ] - Ring_Setting[2 ]; rotor_out = ((rotor_out - 'A' ) + delta + 26 ) % 26 + 'A' ; for (int j=0 ; j<26 ; j++) if (rotor_out == rotor_table[num_rotor[2 ]-1 ][j]) { rotor_out = 'A' + j; break ; } rotor_out = ((rotor_out - 'A' ) - delta + 26 ) % 26 + 'A' ; for (int j=0 ; j<26 ; j++) if (rotor_out == plug_board[j]) { after_pb = 'A' + j; break ; } res += after_pb; } return res; }