《应用密码学》——第二章 古典密码技术

2.1 替代密码

单表替代密码

一般单表替代密码

a b c d e f g h i j k l m n o p q i s t u v w x y z
q w e r t y u i o p a s d f g h j k l z x c v b n m

明文根据转化表将明文字母转换为密文字母(a -> q),密钥是键盘字母的排序

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
#include<iostream>
#include<string>
using namespace std;

string table_c = "qwertyuiopasdfghjklzxcvbnm";
string table_m = "abcdefghijklmnopqrstuvwxyz";
int N = 26;


int index(char x)
{
for(int i=0;i<N;i++)
{
if(table_c[i]==x)return i;
}
}
string pi_1(string c)
{
string temp_m = "";
int n;
for(int i=0;i<N;i++)
{
n = index(c[i]);
temp_m += table_m[n];
}
return temp_m;
}
string pi(string m)
{
string temp_c="";
int n;
for(int i=0;i<N;i++)
{
n = m[i]-'a';
temp_c += table_c[n];
}
return temp_c;
}
int main()
{
string m = "abcdefghijklmnopqrstuvwxyz";
string c = "qwertyuiopasdfghjklzxcvbnm";
cout<<pi(m)<<endl;
cout<<pi_1(c)<<endl;
return 0;
}

移位密码

img

img

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
#include<iostream>
#include<string>
using namespace std;

string c = "efghijklmnopqrstuvwxyzabcd";
string m = "abcdefghijklmnopqrstuvwxyz";
int n = 26;
string pi_1(string c)
{
string temp_m = "";
int k_1 = 4;
for(int i=0;i<n;i++)
{
temp_m += (c[i]-'a'-k_1+26)%26 + 'a';
}
return temp_m;
}
string pi(string m)
{
string temp_c = "";
int k = 4;
for(int i=0;i<n;i++)
{
temp_c += (m[i]-'a'+ k)%26 + 'a';
}
return temp_c;
}
int main()
{
cout<<pi(m)<<endl;
cout<<pi_1(c)<<endl;

return 0;
}

仿射密码

这边写错了,k1=7,取模的26不是k2,而且只有7,26互质(最大公因数为1)才能解密:ax-by=1

img点击并拖拽以移动

扩展欧几里德变换求a逆: img

欧几里得算法非递归求逆密钥

img

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
#include<iostream>
#include<string>
using namespace std;

string Atoa(string x);
string E(string x);
//a指进行乘法逆元的密钥,b指的模的那个数
int gcd(int a,int b);//欧几里德算法求公约数
int bianli(int a,int b);//暴力计算
int ex_gcd(int a,int b,int &x,int &y);//扩展欧几里德算法递归求逆密钥
int gcd_1(int a,int b,int &x,int &y)//欧几里得算法非递归求逆密钥
string D(string x);

int main()
{
string m,c;
cout<<"请输入明文m:";
cin>>m;
//m = "China";
//c = "UnwPc";
//cout<<Atoa(m)<<endl;
cout<<"E(m)="<<E(m)<<endl;
//cout<<gcd(9,26)<<endl;
cout<<"请输入密文c:";
cin>>c;
cout<<"D(c)="<<D(c)<<endl;
return 0;
}


string Atoa(string x)
{
string temp="";
int n = x.size();
for(int i=0;i<n;i++)
{
if(x[i]>'Z')
temp += x[i];
else
temp += x[i]-'A'+'a';
}
return temp;
}
string E(string x)
{
x = Atoa(x);
string temp="";
int k1=9,k2=2,m=26;
int n = x.size();
for(int i=0;i<n;i++)
{
temp += (k1*(x[i]-'a')+k2)%m+'a';
}
return temp;
}
int gcd(int a,int b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
int bianli(int a,int b)
{
int x;
for(int i=1;i<=b;i++)
{
x = (a*i)%b;
if(x==1)return i;
}
}
string D(string x)
{
x = Atoa(x);
string temp="";
int k1=9,k2=2,m=26,n,k1_1;
int flag=gcd(k1,m);
if(flag!=1)
{
cout<<"k1与m不互质,无法解密!"<<endl;
return temp;
}
else
{
//k1_1=bianli(k1,m);
int x0=0,y0=0;
k1_1 = gcd_1(k1,m,x0,y0);

n = x.size();
for(int i=0;i<n;i++)
{
temp += k1_1*(x[i]-'a'-k2)%m +'a';
}
return temp;
}
}
int ex_gcd(int a,int b,int &x,int &y)//扩展欧几里德变换ax+by=gcd(a,b)
{
if(b==0)
{
x=1;
y=0;
//cout<<k++<<" dao di le"<<endl;
return a;

}
int res = ex_gcd(b,a%b,x,y);
//通过证明得,如何获得上一层x,y
//x1=y2,y1=x2-(a/b)*y2
int temp=x;
x = y;
y = temp-(a/b)*y;
//cout<<k++<<" "<<x<<" "<<y<<" "<<res<<endl;
return x;
}
int gcd_1(int a,int b,int &x,int &y)//欧几里得算法非递归求逆密钥
{
int X1=1,X2=0,X3=b;
int Y1=0,Y2=1,Y3=a;
int T1,T2,T3;
int Q;
while(1)
{
if(Y3==0)return X2;
if(Y3==1)return Y2;

Q=X3/Y3;
T1=X1-Q*Y1;
T2=X2-Q*Y2;
T3=X3-Q*Y3;

X1=Y1;X2=Y2;X3=Y3;
Y1=T1;Y2=T2;Y3=T3;
}
}

密钥短语密码

img

选用一个英文单词或单词串作为密钥。去掉重复字母的到一个字符串排在首端将字母表其余字母依次写入。其他类似一般单表替代密码

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
#include<iostream>
using namespace std;

string Table_m="";
char Table_c[26];

void creatTable(char letter[]);
string Atoa(string x);
string E(string x);
string D(string x);

int main()
{

string m,c;
char letter[26];
m = "China";
c = "yfgmk";

for(int i=0;i<26;i++)
{
letter[i]='a'+i;
}
creatTable(letter);
//cout<<Table<<endl;
cout<<"请输入明文m:";
cin>>m;
cout<<"E(m)="<<E(m)<<endl;
cout<<"请输入密文c:";
cin>>c;
cout<<"D(c)="<<D(c)<<endl;

return 0;
}
void creatTable(char letter[])
{
string k="key";
Table_m += k;
int n=k.size(),index;
for(int i=0;i<n;i++)
{
index = k[i]-'a';
letter[index]='0';
}
for(int i=0;i<26;i++)
{
if(letter[i]!='0')
Table_m += letter[i];
}
for(int i=0;i<26;i++)
{
index = Table_m[i]-'a';
Table_c[index]=letter[i];
}
}
string Atoa(string x)
{
string temp="";
int n = x.size();
for(int i=0;i<n;i++)
{
if(x[i]>'Z')
temp += x[i];
else
temp += x[i]-'A'+'a';
}
return temp;
}
string E(string x)
{
int n=x.size(),index;
string temp="";
x = Atoa(x);
for(int i=0;i<n;i++)
{
index=x[i]-'a';
temp += Table_m[index];
}
return temp;
}
string D(string x)
{
int n=x.size(),index;
string temp="";
for(int i=0;i<n;i++)
{
index = x[i]-'a';
temp += Table_c[index];
}
return temp;
}

多表替代密码

维吉尼亚密码

img

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
#include<iostream>
#include<string>
using namespace std;

string Atoa(string x);
string E(string x);
string D(string x);

int main()
{
string m,c;
//m = "appliedcryptosystem";
//c = "cxesmvfkgftkqanzxvo";
cout<<"请输入明文m:";
getline(cin,m);
cout<<"E(m)="<<E(m)<<endl;

cout<<"请输入密文c:";
getline(cin,c);
cout<<"D(c)="<<D(c)<<endl;
return 0;
}
string Atoa(string x)
{
string temp="";
int n = x.size();
for(int i=0;i<n;i++)
{
if(x[i]==' ')continue;
if(x[i]>'Z')
temp += x[i];
else
temp += x[i]-'A'+'a';
}
return temp;
}
string E(string x)
{
string k="chipher";
k=Atoa(k);
string temp="";
int index;
x = Atoa(x);
int n=x.size();
for(int i=0;i<n;i++)
{
index=i%6;
temp += (k[index]-'a'+x[i]-'a')%26+'a';
}
return temp;
}
string D(string x)
{
string k="chipher";
k=Atoa(k);
string temp="";
int index;
int n=x.size();
for(int i=0;i<n;i++)
{
index=i%6;
temp += (x[i]-k[index]+26)%26+'a';
}
return temp;
}

希尔(Hill)密码

密钥是一个矩阵,解密是其逆矩阵

img img
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
后期还要观摩别人的代码将思路进行优化。我觉得我的思路还是比较暴力的,而且有些地方代码重复性比较高,比如加解密矩阵相乘得结果是一样的步骤可以合并,求逆矩阵可以再封成一个函数但现在我还是把他直接写在解密函数里。感觉求解|A|可以利用三阶那个函数迭代……
相关知识点转看博客:涉及的C/C++的知识点
*/
#include<iostream>
#include<stdlib.h>
#include<math.h>
using namespace std;

//以密钥矩阵可逆,加解密成功为前提条件
int threeOrder_evaluation(int N,int **K);//三阶行列式|A|求值(对角线方法只适用于二、三阶)
int Evaluation_of_Determinant(int N,double **K);//n阶行列式求值 / 判断矩阵是否可逆|A|?=0
double **Adjoint_Matrix(int N,double **K);//求伴随矩阵A*
string E(string x);
string D(string x);

int main()
{
string c,m;
m = "good";
c = "wmwl";

cout<<"E(m) = "<<E(m)<<endl;
cout<<"D(c) = "<<D(c)<<endl;

return 0;
}



string D(string x)
{
int n=x.size(),N=2;
int K[N][N]={{11,8},{3,7}};//53
//int K[N][N]={{1,1,1},{0,1,3},{2,2,5}};//3
//int K[N][N]={{3,1,1,1},{1,3,1,1},{1,1,3,1},{1,1,1,3}};//48
int evaluation;//|A|
int K_1[N][N];
int M[N],C[N];
string temp="";

//创建动态二维数组
double **Key;//密钥A
double **BanSui;//伴随矩阵
Key = (double **)malloc(N*sizeof(double *));//行开辟空间
for(int i=0;i<N;i++)//列开辟空间
*(Key+i)=(double*)malloc(N*sizeof(double));
//*(BanSui+i)=(double*)malloc(N*sizeof(double));
for(int i=0;i<N;i++)//将值输入动态数组
for(int j=0;j<N;j++)
Key[i][j]=K[i][j];

//求A*
BanSui = Adjoint_Matrix(N,Key);

//求|A|
evaluation = Evaluation_of_Determinant(N,Key)%26;

//求A逆
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
K_1[i][j]=((int(BanSui[i][j])/evaluation)+26)%26;

//解密
for(int i=0;i<n;i++)
{
M[i%N]=x[i]-'a';
if(i%N==N-1)
{
for(int j=0;j<N;j++)
{
C[j]=0;
for(int k=0;k<N;k++)
{
C[j] += M[k]*K_1[j][k];
}
temp += C[j]%26 + 'a';
}
}
}

for(int i=0;i<N;i++)//释放空间:行
{
free(*(Key+i));
free(*(BanSui+i));
}

return temp;
}

double **Adjoint_Matrix(int N,double **K)
{

double **adjoint,**cofactor;//伴随矩阵,代数余子式
int m,n;
int temp[N][N];

//创建动态数组
adjoint = (double **)malloc(N*sizeof(double));
for(int i=0;i<N;i++)
adjoint[i] = (double *)malloc(N*sizeof(double));
cofactor = (double **)malloc(N*sizeof(double));
for(int i=0;i<N;i++)
cofactor[i] = (double *)malloc(N*sizeof(double));

//求n=2阶伴随矩阵
if(N==2)
{
m=0,n=0;
for(int i=N-1;i>-1;i--)
{
for(int j=N-1;j>-1;j--)
{
adjoint[m++][n]=pow(-1,i+j)*K[i][j];
}
m=0;
n++;
}
return adjoint;
}
//求n>2阶伴随矩阵
for(int i=0;i<N;i++)
{
m=0,n=0;
for(int k=0;k<N;k++)
{
if(k==i)continue;
for(int l=0;l<N;l++)
{
temp[m][n++]=K[k][l];
}
m++;
n=0;
}

for(int j=0;j<N;j++)
{
m=0,n=0;
for(int l=0;l<N;l++)
{
if(l==j)continue;
for(int k=0;k<N-1;k++)
{
cofactor[m++][n]=temp[k][l];
//cout<<m-1<<" "<<n<<" "<<temp[k][l]<<" "<<k<<" "<<l<<endl;
}
n++;
m=0;
//cout<<endl;
}
//伴随矩阵
adjoint[j][i]=pow(-1,i+j)*K[i][j]*Evaluation_of_Determinant(N-1,cofactor);
}
}

return adjoint;
}

string E(string x)
{
int n=x.size(),N=2;
int K[N][N]={{11,8},{3,7}};
int M[N],C[N];
string temp="";

for(int i=0;i<n;i++)
{
M[i%N]=x[i]-'a';
if(i%N==N-1)
{
for(int j=0;j<N;j++)
{
C[j]=0;
for(int k=0;k<N;k++)
{
C[j] += M[k]*K[j][k];
}
temp += C[j]%26 + 'a';
}
}
}
return temp;
}
int threeOrder_evaluation(int N,int **K)//三阶矩阵求值(对角线方法只适用于二、三阶)
{
int k,sum=0;
int Temp[N][2*N-1];

//第一步:形成对称矩阵
for(int i=0;i<N;i++)
{
for(int j=0;j<2*N-1;j++)
{
Temp[i][j]=K[i][j%N];
cout<<Temp[i][j]<<" ";
}
cout<<endl;
}
//第二步:求出每个ai*aj*ak*al
int cunzhi1[N],cunzhi2[N];
for(int i=0;i<N;i++)
{
cunzhi1[i]=1;
k=0;
for(int j=i;j<i+N;j++)
{
cunzhi1[i] *= Temp[k++][j];
cout<<cunzhi1[i]<<" ";
}
cout<<endl;
}
for(int i=0;i<N;i++)
{
cunzhi2[i]=1;
k=0;
for(int j=N+i-1;j>N+i-4;j--)
{
cunzhi2[i] *= Temp[k++][j];
cout<<cunzhi2[i]<<" ";
}
cout<<endl;
}
//第三步:求出矩阵的值
for(int i=0;i<N;i++)
{
sum += cunzhi1[i]-cunzhi2[i];
}
return sum;
}
int Evaluation_of_Determinant(int N,double **K)//n阶行列式求值
{
float z,ji=1,sum=1;
int p=0;
for(int i=0;i<N-1;i++)//列
{
z = K[i][i];
//这块解决当为{{0,1},{2,3}}这样矩阵时的情况
while(z==0)
{
p++;
for(int k=0;k<N;k++)
{
K[i][k]+= K[i+p][k];
}
z=K[i][i];
}
p=0;

ji *= z;
//cout<<z<<" "<<ji<<endl;
for(int k=i;k<N;k++)
{
K[i][k] /= z;
//cout<<i<<" "<<k<<" "<<K[i][k]<<endl;
}

for(int j=i+1;j<N;j++)//行
{
z = K[j][i];
if(z==0)continue;
//cout<<z<<endl;
for(int k=i;k<N;k++)
{
K[j][k] -= z*K[i][k];
//cout<<j<<" "<<k<<" "<<K[j][k]<<" "<<i<<" "<<k<<" "<<K[i][k]<<endl;
}
}
}

for(int i=0;i<N;i++)
{
sum *= K[i][i];
//cout<<sum<<" ";
}
//cout<<endl;
return sum*ji;
}

一次一密密码(One Time Pad)

Playfair 密码

img

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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#include<iostream>
#include<string>
using namespace std;

char keyTable[6][6];
string key;

void Modify_key(string k);//密钥创建+内容修改
string Modify_m(string x);//明文格式内容修改
string Modify_c(string x);
void Init();
int index(char x);
string E(string x);
string D(string x);


int main()
{
string m,c;
//m="playfair cipher";
//c="layfpyrsmramcd";

Init();

cout<<"请输入明文m:";
getline(cin,m);
cout<<"E(m)="<<E(m)<<endl;

cout<<"请输入密文c:";
getline(cin,c);
cout<<"D(c)="<<D(c)<<endl;

return 0;
}

string Modify_c(string x)
{
string temp="";
int n=x.size();
char k='x';
for(int i=0;i<n;i++)
{
if(x[i]==x[i+2]&&x[i+1]==k)
{
temp+=x[i];
temp+=x[i+2];
i += 2;
continue;
}
if(x[n-1]==k)continue;
temp += x[i];
}
return temp;
}
string D(string x)
{
int n=x.size(),N1,N2,x1,x2,y1,y2;
string temp="";
for(int i=0;i<n;i+=2)
{
N1=index(x[i]);
N2=index(x[i+1]);
x1=N1/5;y1=N1%5;
x2=N2/5;y2=N2%5;

if(x1==x2)
{
y1=(y1+4)%5;
y2=(y2+4)%5;
temp+=keyTable[x1][y1];
temp+=keyTable[x2][y2];
}
else if(y1==y2)
{
x1=(x1+4)%5;
x2=(x2+4)%5;
temp+=keyTable[x1][y1];
temp+=keyTable[x2][y2];
}
else
{
temp+=keyTable[x1][y2];
temp+=keyTable[x2][y1];
}
}
temp=Modify_c(temp);
return temp;
}

string Modify_m(string x)
{
int n=x.size();
char k='x';
string temp="",temp1="";
for(int i=0;i<n;i++)
{
if(x[i]==' ')continue;
temp1+=x[i];
}
n=temp1.size();
for(int i=0;i<n;i+=2)
{
temp+=temp1[i];
if(x[i]==x[i+1])
{
temp+=k;
i--;
continue;
}
temp+=temp1[i+1];
}
n=temp.size();
if(n%2!=0)temp+=k;
return temp;
}
void Modify_key(string k)
{
int n=k.size(),index,flag=1;
int x=0,y=0;
char letter[26];
string temp="";
//关于去重:可以创建一个顺序的字母数组,循环的时候当key中第一次出现该字符将索引值下内容改为‘0’,下一次再遇到该值因为为‘0’所以就不管啦
for(int i=0; i<26; i++)
{
letter[i]='a'+i;
}
for(int i=0; i<n; i++)
{
if(k[i]==' ')continue;
else
{
index = k[i]-'a';
if(k[i]==letter[index])
{
temp += k[i];
letter[index]='0';
if(k[i]=='i'||k[i]=='j')flag=0;
}
}
}
for(int i=0; i<26; i++)
{
if(flag==1&&(k[i]=='i'||k[i]=='j'))
{
temp+=letter[i];
flag = 0;
}
if(letter[i]!='0'&&k[i]!='i'&&k[i]!='j')
{
temp += letter[i];
}
if(letter[i]=='w')temp+=letter[i];//不知道为啥w就是判断不了QAQ
}
key = temp;
for(int i=0;i<25;i++)
{
keyTable[x][y]=temp[i];
y++;
if(y%5==0)
{
x++;
y=0;
}
}
}
int index(char x)
{
int i;
for(i=0;i<26;i++)
{
if(key[i]==x)break;
}
return i;
}
string E(string x)
{
string temp="";
x=Modify_m(x);
int n=x.size(),N1,N2,x1,x2,y1,y2;
for(int i=0;i<n;i+=2)
{
N1=index(x[i]);
N2=index(x[i+1]);
x1=N1/5;y1=N1%5;
x2=N2/5;y2=N2%5;
if(x1==x2)
{
y1=(y1+1)%5;
y2=(y2+1)%5;
temp+=keyTable[x1][y1];
temp+=keyTable[x2][y2];
}
else if(y1==y2)
{
x1=(x1+1)%5;
x2=(x2+1)%5;
temp+=keyTable[x1][y1];
temp+=keyTable[x2][y2];
}
else
{
temp+=keyTable[x1][y2];
temp+=keyTable[x2][y1];
}
}
return temp;
}
void Init()
{
string k="playfair is a digram cipher";
Modify_key(k);
}

2.2 置换密码

周期置换密码

给予的明文必须是以密钥k的倍数形式(因为要以k个字母为一组进行每组置换)

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
#include<iostream>
using namespace std;

string E(string x)
string D(string x)

int main()
{
string m,c;
m = "cryptographycry";
c = "ytcoprahgypr";

cout<<"E(m)="<<E(m)<<endl;
cout<<"D(c)="<<D(c)<<endl;

return 0;

}


string E(string x)
{
int k=6;
int k_m[k]={2,4,0,5,3,1};
int n=x.size(),index,flag=0;
string temp1="",temp2="";

for(int i=0;i<n;i++)
{
temp1 += x[i];
if(i%k==5)
{
for(int i=0;i<6;i++)
{
index = k_m[i];
temp2+= temp1[index];
}
temp1 = "";
}
}

return temp2;

}
string D(string x)
{
int k=6;
int k_m[k]={2,4,0,5,3,1};
int k_c[k];
for(int i=0;i<k;i++)
{
for(int j=0;j<k;j++)
{
if(k_m[j]==i)
{
k_c[i]=j;
// cout<<j<<endl;
break;
}
}
}
int n=x.size(),index;
string temp1="",temp2="";
for(int i=0;i<n;i++)
{
temp1 += x[i];
if(i%k==5)
{
for(int i=0;i<6;i++)
{
index = k_c[i];
temp2+= temp1[index];
//cout<<index<<temp2<<endl;
}
temp1 = "";
}
}
return temp2;
}
/*
1 2 3 4 5 6
3 5 1 6 4 2
1 2 3 4 5 6
3 6 1 5 2 4
*/

列置换密码

原本解密想不用数组的……但没写出比较好的QAQ

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
#include<iostream>
using namespace std;

string Modify_m(string x);
string E(string x);
string D(string x);

int main()
{
string m,c;
m = "This boy is a worker Th";
//c = "sioriywehoaktbsr";
c = "sioriywehoakhtbsrt";
cout<<"E(m)="<<E(m)<<endl;
cout<<"D(c)="<<D(c)<<endl;

return 0;
}

string Modify_m(string x)
{
int n=x.size();
string temp="";
for(int i=0;i<n;i++)
{
if(x[i]==' ')continue;
if(x[i]<'a')
temp += x[i]-'A'+'a';
else
temp += x[i];
}
return temp;
}
string E(string x)
{
x = Modify_m(x);
int n=x.size(),k=4,index;
int k_m[k]={3,2,1,0};
string temp0="",temp1="",temp2="";
if(n%k!=0)
{
for(int i=0;i<k-n%k;i++)
x += '?';
n += k-n%k;
}
for(int i=0;i<n;i++)
{
temp0 += x[i];
if(i%k==3)
{
for(int i=0;i<k;i++)
{
index = k_m[i];
temp1 += temp0[index];
}
temp0="";
}
}
for(int i=0;i<k;i++)
{
for(int j=i;j<n;j+=k)
{
if(temp1[j]=='?')
continue;
else
temp2 += temp1[j];
}
}
return temp2;
}
string D(string x)
{
int n=x.size(),k=4,m=n/4+1,p=0;
int k_m[k]={3,2,1,0},k_c[k];
string temp="";
char table[m][k];
for(int i=0;i<k;i++)
{
for(int j=0;j<k;j++)
{
if(k_m[j]==i)
{
k_c[i]=j;
break;
}
}
}
if(n%4==0)m=n/4;
for(int i=0;i<k;i++)
{
for(int j=0;j<m;j++)
{
if(j==m-1&&k_m[i]>(n-1)%4)
{
table[j][i]='?';
p++;
}
else
table[j][i]=x[i*m+j-p];
//cout<<j<<" "<<i<<" "<<i*m+j-p<<" "<<table[j][i]<<endl;
}
}

for(int i=0;i<m;i++)
{
for(int j=0;j<k;j++)
{
p=k_c[j];
if(table[i][p]=='?')continue;
else
temp += table[i][p];
//cout<<i<<" "<<" "<<p<<" "<<table[i][p]<<endl;
}
}
return temp;
}

2.3 转轮机密码

艾尼格玛,多表替代,密钥:三个轮子的初态