1 //Playfair密码
2 /*理解算法最重要,最好自己动手实现试试看,可以使用MFC写一个简单的交互界面*/
3 #include<iostream>
4 #include<cstring>
5
6 using namespace std;
7 void encrypt()
8 {
9 const int N=100;
10 char letters[26]="ABCDEFGHIKLMNOPQRSTUVWXYZ";//用于填充矩阵
11 int flag[25]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//字母是否已在矩阵中,与letters数组对应
12 char ch[5][5];//5X5矩阵
13 char ch1[N];//密钥
14 char ch2[N];//明文
15 char ch4;//无关字符
16 int len='a'-'A';
17 cout<<"输入密钥:";
18 cin>>ch1;
19 int flg=1;
20 while(flg==1)
21 {
22 for(int i=0;i<strlen(ch1);i++)//把所输入的密钥转化为大写字母
23 {
24 if(ch1[i]>'z'||ch1[i]<'a')
25 {
26 cout<<"请重新选择操作:"<<endl;
27 flg=0;break;
28 }
29 else
30 ch1[i]=ch1[i]-len;
31 }
32 if(flg==1)
33 { for(int i=0;i<strlen(ch1);i++)//把密钥中的J都变为I
34 {
35 if(ch1[i]=='J')ch1[i]='I';
36 }
37 int i=0;int j=0;
38 //把密钥中的字母填入到矩阵中,并把该字母标记为已用
39 for(int k=0;k<strlen(ch1);k++)
40 {
41 for(int t=0;t<25;t++)
42 {
43 if(ch1[k]==letters[t]&&flag[t]==0)
44 {
45 ch[i][j]=letters[t];
46 flag[t]=1;
47 if(j<4)j++;
48 else {i++;j=0;}
49 }
50 }
51 }
52 for( int k=0;k<25;k++)//按字母表顺序把未用字母依次填入到矩阵中
53 {
54 if(flag[k]==0)
55 {
56 ch[i][j]=letters[k];
57 flag[k]=1;
58 if(j<4)j++;
59 else{i++;j=0;}
60 }
61 }
62 cout<<"密钥填充后的矩阵为: "<<endl;
63 for(i=0;i<5;i++)
64 for(j=0;j<5;j++)
65 {
66 cout<<ch[i][j];
67 cout<<" ";
68 if(j==4)
69 cout<<endl;
70 }
71 cout<<endl;
72 cout<<"请输入明文(请输入英文字符):";
73 cin>>ch2;
74 cout<<"输入一个无关字符:";
75 cin>>ch4;
76 if(ch4>='a')
77 ch4=ch4-len;
78 for(int k=0;k<strlen(ch2);k++)//把所输入的明文转化为大写字母
79 {
80 if(ch2[k]>='a')
81 ch2[k]=ch2[k]-len;
82 }
83 for(int k=0;k<strlen(ch2);k++)//把明文中的J都变为I
84 {
85 if(ch2[k]=='J')
86 ch2[k]='I';
87 }
88 //为明文添加必要的无关字符以防止同一组的两个字符相同
89 for( int k=0;k<strlen(ch2);k+=2)
90 {
91 if(ch2[k]==ch2[k+1])
92 {
93 for(int t=strlen(ch2);t>k;t--)
94 ch2[t+1]=ch2[t];
95 ch2[k+1]=ch4;
96 }
97 }
98 //若明文有奇数个字符,则添加一个无关字符以凑够偶数个
99 if(strlen(ch2)%2!=0)
100 {
101 ch2[strlen(ch2)+1]=ch2[strlen(ch2)];//字符串结尾赋'\0'
102 ch2[strlen(ch2)]=ch4;//明文串尾插入无关字符
103 }
104 cout<<"经过处理后的明文为:";
105 for(int k=0;k<strlen(ch2);k+=2)
106 cout<<ch2[k]<<ch2[k+1]<<" ";
107 cout<<endl;
108 cout<<"其最终长度为:"<<strlen(ch2)<<endl;
109 //////////////////明文输入并整理完毕///////////////////////////////
110 for(int k=0;k<strlen(ch2);k+=2)
111 {
112 int m1,m2,n1,n2;
113 for(m1=0;m1<=4;m1++)
114 {for(n1=0;n1<=4;n1++)
115 {
116 if(ch2[k]==ch[m1][n1])break;
117 }
118 if(ch2[k]==ch[m1][n1])break;
119 }
120 for(m2=0;m2<=4;m2++)
121 {
122 for(n2=0;n2<=4;n2++)
123 {
124 if(ch2[k+1]==ch[m2][n2])break;
125 }
126 if(ch2[k+1]==ch[m2][n2])break;
127 }
128 m1=m1%5;
129 m2=m2%5;
130 if(n1>4){n1=n1%5;m1=m1+1;}
131 if(n2>4){n2=n2%5;m2=m2+1;}
132 if(m1==m2)
133 {
134 ch2[k]=ch[m1][(n1+1)%5];
135 ch2[k+1]=ch[m2][(n2+1)%5];
136 }
137 else
138 {
139 if(n1==n2)
140 {
141 ch2[k]=ch[(m1+1)%5][n1];
142 ch2[k+1]=ch[(m2+1)%5][n2];
143 }
144 else
145 {ch2[k]=ch[m1][n2];
146 ch2[k+1]=ch[m2][n1];
147 }
148 }
149 }
150 cout<<"加密后所得到的密文是:";
151 for(int k=0;k<strlen(ch2);k+=2)
152 cout<<ch2[k]<<ch2[k+1]<<" ";
153 cout<<endl;
154 }else break;
155 }
156
157 }
158
159 //解密算法
160 void decrypt()
161 {
162 const int N=100;
163 char letters[26]="ABCDEFGHIKLMNOPQRSTUVWXYZ";//用于填充矩阵
164 int flag[25]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
165 //标记字母是否已在矩阵中,与letters数组对应
166 char ch[5][5];//5X5矩阵
167 char ch1[N];//密钥
168 char ch2[N];//密文
169 int len='a'-'A';
170 int flg=1;
171 cout<<"输入密钥:";
172 cin>>ch1;
173 while(flg==1)
174 {
175 for(int i=0;i<strlen(ch1);i++)//把所输入的密钥转化为大写字母
176 {if(ch1[i]>'z'||ch1[i]<'a')
177 {
178 cout<<"请重新选择操作:"<<endl;
179 flg=0;break;
180 }
181 else
182 ch1[i]=ch1[i]-len;
183 }
184 if(flg==1)
185 { for(int i=0;i<strlen(ch1);i++)//把密钥中的J都变为I
186 {
187 if(ch1[i]=='J')ch1[i]='I';
188 }
189 int i=0;int j=0;
190 //把密钥中的字母填入到矩阵中,并把该字母标记为已用
191 for(int k=0;k<strlen(ch1);k++)
192 {
193 for( int t=0;t<25;t++)
194 {
195 if(ch1[k]==letters[t]&&flag[t]==0)
196 {
197 ch[i][j]=letters[t];
198 flag[t]=1;
199 if(j<4)j++;
200 else {i++;j=0;}
201 }
202 }
203 }
204 for( int k=0;k<25;k++)//按字母表顺序把未用字母依次填入到矩阵中
205 {
206 if(flag[k]==0)
207 {
208 ch[i][j]=letters[k];
209 flag[k]=1;
210 if(j<4)j++;
211 else{i++;j=0;}
212 }
213 }
214 cout<<"密钥填充后的矩阵为: "<<endl;
215 for(i=0;i<5;i++)
216
217 for(j=0;j<5;j++)
218 {
219 cout<<ch[i][j];
220 cout<<" ";
221 if(j==4)
222 cout<<endl;
223 }
224 cout<<endl;
225 /////////////////////矩阵生成完毕////////////////////////////
226 int f=0;
227 do{
228 cout<<"请输入密文(英文字符):";
229 cin>>ch2;
230 for(int k=0;k<strlen(ch2);k++)//把所输入的密文转化为大写字母
231 {
232 if(ch2[k]>='a')
233 ch2[k]=ch2[k]-len;
234 }
235 for( int k=0;k<strlen(ch2);k++)//把密文中的J都变为I
236 {
237 if(ch2[k]=='J')ch2[k]='I';
238 }
239 for( int k=0;k<strlen(ch2);k+=2)
240 {
241 if(ch2[k]==ch2[k+1])
242 {
243 cout<<"同一分组中不能出现相同字符!请重新输入。"<<endl;
244 f=1;
245 break;
246 }else f=2;
247 }
248 if(f==1)continue;
249 if(strlen(ch2)%2!=0)
250 {
251 cout<<"字符串不能为奇数个!请重新输入。"<<endl;
252 f=1;
253 }
254 else f=2;
255 }while(f==1);
256 //解密开始
257 for( int k=0;k<strlen(ch2);k+=2)
258 {
259 int m1,m2,n1,n2;
260 for(m1=0;m1<=4;m1++)
261 {
262 for(n1=0;n1<=4;n1++)
263 {
264 if(ch2[k]==ch[m1][n1])break;
265 }
266 if(ch2[k]==ch[m1][n1])break;
267 }
268 for(m2=0;m2<=4;m2++)
269 {
270 for(n2=0;n2<=4;n2++)
271 {
272 if(ch2[k+1]==ch[m2][n2])break;
273 }
274 if(ch2[k+1]==ch[m2][n2])break;
275 }
276 m1=m1%5;
277 m2=m2%5;
278 if(n1>4){n1=n1%5;m1=m1+1;}
279 if(n2>4){n2=n2%5;m2=m2+1;}
280 if(m1==m2)
281 {ch2[k]=ch[m1][(n1+4)%5];
282 ch2[k+1]=ch[m2][(n2+4)%5];
283 }
284 else
285 {
286 if(n1==n2)
287 {
288 ch2[k]=ch[(m1+4)%5][n1];
289 ch2[k+1]=ch[(m2+4)%5][n2];
290 }
291 else
292 {
293 ch2[k]=ch[m1][n2];
294 ch2[k+1]=ch[m2][n1];
295 }
296 }
297 }
298 cout<<"解密后所得到的明文是:";
299 for(int k=0;k<strlen(ch2);k+=2)
300 cout<<ch2[k]<<ch2[k+1]<<" ";
301 cout<<endl;
302 }
303 else break;
304 }
305
306 }
307
308 int main()
309 {
310
311 int n;
312 cout<<"请选择1加密2解密:"<<endl;
313 while(true)
314 {
315 cin>>n;
316 switch(n)
317 {
318 case 1:
319 encrypt();
320 break;
321 case 2:
322 decrypt();
323 break;
324 default:
325 break;
326 }
327 }
328 return 0;
329 }