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";
/*ABCDEFGHIJKLMNOPQRSTUVWXYZ*/
char input = 'D';
char output = plug[input-'A'];

Rotor(转子)

1
2
3
4
5
6
7
8
9
char rotor_table[5][27] = 
{
//ABCDEFGHIJKLMNOPQRSTUVWXYZ
"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
// 1,2,3,4,5号转子的下一个字母是这些时,转动就要带动左边的转
char step_char[6] = "RFWKA"; // Royal Flags Wave Kings Above

如果我们选择转子是123,当2处于E,3处于V时,加密下一个字符三个转子都要动一圈,这被称为double step

Reflector(反射板)

没什么好说的就是一个字符替换

1
2
//          ABCDEFGHIJKLMNOPQRSTUVWXYZ
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
						 //”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
char plug[27] ="AGDCRVBNUKJMLHPOQESYIFWXTZ";
// C->D

然后按 5->2->1 的顺序依次过转子

1
output = rotor_table[x][input-'A']
1
2
3
4
5
6
// delta = (Y+1) - P = 10
// D + delta -> N
// ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
char rotor_table[5] = "VZBRGITYUPSDNHLXAWMJQOFECK"
// N -> H
// H - delta -> X
1
2
3
4
5
6
// delta = R - I = 9
// X + delta -> G
// ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
char rotor_table[2] = "AJDKSIRUXBLHWTMCQGZNPYFVOE"
// G -> R
// R - delta -> I
1
2
3
4
5
6
// delta = C - T = 9
// I + delta -> R
// ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
char rotor_table[1] = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"
// R -> U
// U - delta -> L

再过reflector

1
2
3
//								 ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
char reflector[] = "YRUHQSLDPXNGOKMIEBFZCWVJAT";
// L->G

然后再按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
// delta = C - T = 9
// G + delta -> P
char rotor_table[1] = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"
// ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
// P -> T
// T - delta -> K
1
2
3
4
5
6
// delta = R - I = 9
// K + delta -> T
char rotor_table[2] = "AJDKSIRUXBLHWTMCQGZNPYFVOE"
// ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
// T -> N
// N - delta -> E
1
2
3
4
5
6
// delta = (Y+1) - P = 10
// E + delta -> O
char rotor_table[5] = "VZBRGITYUPSDNHLXAWMJQOFECK"
// ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
// O -> V
// V - delta -> L

最后再过一次Plug_Board ,这里也需反查

1
2
3
char plug[27]	="AGDCRVBNUKJMLHPOQESYIFWXTZ";
// ”ABCDEFGHIJKLMNOPQRSTUVWXYZ“
// L->M

可以发现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;
// ABCDEFGHIJKLMNOPQRSTUVWXYZ
char reflector[] = "YRUHQSLDPXNGOKMIEBFZCWVJAT";
char rotor_table[5][27] =
{
//ABCDEFGHIJKLMNOPQRSTUVWXYZ
"EKMFLGDQVZNTOWYHXUSPAIBRCJ",
"AJDKSIRUXBLHWTMCQGZNPYFVOE",
"BDFHJLCPRTXVZNYEIWGAKMUSQO",
"ESOVPZJAYQUIRHXLNFTGKDCMWB",
"VZBRGITYUPSDNHLXAWMJQOFECK"
};
char step_char[6] = "RFWKA"; // Royal Flags Wave Kings Above

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'];

// Message_Key[2] = Message_Key[2]+1;
// if(Message_Key[1] == step_char[num_rotor[1]-1])
// Message_Key[0] += 1;
// if(Message_Key[2] == step_char[num_rotor[2]-1])
// Message_Key[1] += 1;
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';
// cout << "0 : " << rotor_in << endl;
char rotor_out = rotor_table[num_rotor[2]-1][rotor_in-'A'];
// cout << "1 : " << rotor_out << endl;
rotor_out = ((rotor_out - 'A') - delta + 26) % 26 + 'A';
// cout << "2 : " << rotor_out << endl;

delta = Message_Key[1] - Ring_Setting[1];
rotor_in = ((rotor_out - 'A') + delta + 26) % 26 + 'A';
// cout << "0 : " << rotor_in << endl;
rotor_out = rotor_table[num_rotor[1]-1][rotor_in-'A'];
// cout << "1 : " << rotor_out << endl;
rotor_out = ((rotor_out - 'A') - delta + 26) % 26 + 'A';
// cout << "2 : " << rotor_out << endl;

delta = Message_Key[0] - Ring_Setting[0];
rotor_in = ((rotor_out - 'A') + delta + 26) % 26 + 'A';
// cout << "0 : " << rotor_in << endl;
rotor_out = rotor_table[num_rotor[0]-1][rotor_in-'A'];
// cout << "1 : " << rotor_out << endl;
rotor_out = ((rotor_out - 'A') - delta + 26) % 26 + 'A';
// cout << "2 : " << rotor_out << endl;

char ref_out = reflector[rotor_out - 'A'];
// cout << "ref : " << ref_out << endl;
//res += ref_in;

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';
// cout << "3 : " << rotor_out << endl;

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';
// cout << "4 : " << rotor_out << endl;

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;
}
// cout << "5 : " << rotor_out << endl;
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;
}