加密解密五种算法的实现

时间:2024-02-25 14:43:36

1、  实验目的

通过五种加密解密算法的分析与设计,用高级语言实现加密解密过程。通过实验过程理解系统中加密解密的基本思想和实现方法。

2、  实验基本原理与方法

①单字母替换加密方法——恺撒密码

加密方法是把英文字母按字母表的顺序编号作为明文,将密钥定为m,加密算法为将明文加上密钥m,得到密码表,通过相反的过程由密文得到明文。

②单字母替换加密方法——字母倒排序

在加密、解密的过程中明文和密文按照字母表的顺序倒排对应,即A对应Z,B对应Y。  

单字母替换加密方法——单表置换密码      

由密钥Key构造字符置换表,完成加密和解密过程。

④多字母替换加密方法——维吉利亚密码

假设明文m=m1 m2 m3 … mn;密钥k=k1k2 k3 … kn,对应密文c=c1 c2 c3 … cn,密文为:ci=(mi+ki )mod 26 ,26个字母的序号依次为0~25,ci , mi ,,ki是分别是密文明文密钥中第i个字母的序号。

转换加密方法

 通过将明文每m个字符一组按顺序分为若干个字符串,再按照先列后行形成密文,并分析给出解密的方法。或者通过给出一个密钥字符串,将明文按密钥字符串长度按顺序分为若干组字符串,再按照密钥字符串各个字符的顺序形成密文,并分析给出解密的方法。

3 具体实现方法:

①      实验方案简述:

本次实验选择用高级语言C#完成,使用面向对象的思想编程,一来对算法实现了较好的封装,使程序安全性提高,同时通过采用C#Web窗体编程框架,设计了较为直观方面的交互页面,并且对程序输入进行输入合法性验证,提高了程序的用户体验,也保证了程序的稳定运行。本实验根据上述实验的基本原理与方法设计程序算法并予以实现,分别实现了凯撒算法、字母倒排序、单表置换、维吉利亚密码和转化加密方法的加密解密。

②      实验技术路线:

 

1 凯撒算法

凯撒算法较为简单只是按照字母表按照密钥移动形成密文或解密显现原文,但是得注意 ,.\:?等符号的出现,所以List长度为32同时注意边界的判断别入?的加密和a的解密,以及密文中字母大小写部分,所以在进行加密或解密前可以将所有字母转换成与List对应的大学,并统一以大写字母输出。

 

 

 

2 字母倒排序法

字母倒排序法也是较为简单的一种加密解密算法,建立字母表List并将输入按照字母表对应顺讯输出即可。

 

 

 

3 单表置换法

单表置换法与前两种算法的主要区别在于,单表置换法的对应表是先将密钥填入进去再将剩余的字母表字母按照字母表顺序填入,之后以之与字母表对应生成密文或对密文进行解密。该方法注意密钥中可能会出现相同的字母所以要去除密钥中相同字母再生成对应的密文表。

 

 

4 维吉利亚算法

维吉利亚算法是由两个表生成密文,第一个是密文中字母对应字母表中的顺序,第二个是按照密钥顺序构建长度等于密文的参照表,然后由m+n%26得出对应的密文对应List顺讯,解密过程先判断每个字母对应两个表的位置上面的字母在List中的位次大小,作出是否给密文对应表字母对应List顺序+26再减去密钥对应表中对应List位次,即为原文该位置上的字母对应List上的位次。解密过程较加密过程复杂,起初是比较懵的,然后百度了一下该类问题得解决原理,写出了算法并进行测试,没有问题,所以通过。

 

 

5 转换加密方法

转换加密方法有两种,第一种是根据int类型密钥,将输入信息分割成密钥长度的片段并将其进行倒叙排序,然后连接片段并输出,解密过程可以是和加密过程一样的操作进行解密,该过程比较简单,但是得注意不能讲输入信息全部截断成等于密钥长度的片段的情况,这里我使用了栈结构,同时加判断如果栈的长度等于密钥长度将其输出到新的片段字符串,并对不能刚好截成等于密钥长度的片段进行判断标记单独处理。

第二种方法可以设置成第一种方法的重载,我理解的第二种方法是根据密钥长度将输入信息拆分成等于密钥长度的片段,然后将每个片段按照密钥的对应List序号进行排序,之后将各个片段连接并输出。该方法由于涉及将拆分的片段密钥对用List顺序排列,所以我将不能全部拆分成等于密钥长度的片段给其后面补不常见的字符‘!’,进行排序后再将‘!’删除。同时注意密钥中不可以有相同的字符出现,而且解密过程与加密算法是不一样的。其中该过程调试修改了多次,虽然实现了正确的加密解密,但是感觉算法过程比较复杂,在加密过程,先将List字母顺序对应shunxu数组位置,List顺序字母在key出现的位置对应shunxu数组的值,然后将shunxu转换成按照List字母出现顺序的nshunxu,如key=”adbc”,shunxu=0231,nshunxu=0312,再令shuxun=nshunxu。然后按照位置递进,在每个片段截取对应shunxu数组的值。解密时,不需要令shuxun=nshunxu,但是要将不能全部拆分成等于密钥长度的片段还原成带有“!”的加密状态,否则会出现错误。

 

 

 

 

  1 //凯撒算法
  2         public string Caesar(int xuanze, string psd, int key)
  3         {
  4             string List = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ,.\\:?";
  5             psd = psd.ToUpper();
  6             char[] miwen1 = new char[psd.Length];
  7             string miwen;
  8             int i = 0;
  9             if (xuanze == 1)
 10             {
 11                 foreach (char e in psd)
 12                 {
 13                     int m = List.IndexOf(e);
 14 
 15                     if (m + key < List.Length)
 16                     {
 17                         string mm = List.Substring(m + key, 1);
 18                         miwen1[i] = Char.Parse(mm);
 19                         i++;
 20                     }
 21                     else
 22                     {
 23                         string mm = List.Substring((m + key) - List.Length, 1);
 24                         miwen1[i] = Char.Parse(mm);
 25                         i++;
 26                     }
 27 
 28                 }
 29                 miwen = string.Join("", miwen1);
 30                 Console.WriteLine(psd);
 31                 return miwen;
 32             }
 33             else
 34             {
 35                 foreach (char e in psd)
 36                 {
 37                     int m = List.IndexOf(e);
 38                     if (m - key < 0)
 39                     {
 40                         string mm = List.Substring(m + 32 - key, 1);
 41                         miwen1[i] = Char.Parse(mm);
 42                         i++;
 43                     }
 44                     else
 45                     {
 46                         string mm = List.Substring((m - key), 1);
 47                         miwen1[i] = Char.Parse(mm);
 48                         i++;
 49                     }
 50                 }
 51                 miwen = string.Join("", miwen1);
 52                 return miwen;
 53             }
 54         }
 55         //字母倒排序
 56         public string Ainversion(int xuanze, string psd)
 57         {
 58             string List = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 59             psd = psd.ToUpper();
 60             char[] miwen1 = new char[psd.Length];
 61             string miwen;
 62             int i = 0;
 63             if (xuanze == 1)
 64             {
 65                 foreach (char e in psd)
 66                 {
 67                     int m = List.IndexOf(e);
 68                     string mm = List.Substring(List.Length - m - 1, 1);
 69                     miwen1[i] = Char.Parse(mm);
 70                     i++;
 71                 }
 72                 miwen = string.Join("", miwen1);
 73                 return miwen;
 74             }
 75             else
 76             {
 77                 foreach (char e in psd)
 78                 {
 79                     int m = List.IndexOf(e);
 80                     string mm = List.Substring(List.Length - m - 1, 1);
 81                     miwen1[i] = Char.Parse(mm);
 82                     i++;
 83                 }
 84                 miwen = string.Join("", miwen1);
 85                 return miwen;
 86             }
 87         }
 88         //单表置换密码
 89         public string STReplace(int xuanze, string psd, string key)
 90         {
 91             string List = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 92             //先构建一个对应的表吧
 93             string NList;
 94             char[] nList = new char[List.Length];
 95             key = key.ToUpper();
 96             int j = 0;
 97             foreach (char e in List)
 98             {
 99                 if (key.IndexOf(e) == -1)
100                 {
101                     nList[j] = e;
102                     j++;
103                 }
104             }
105             string sList = string.Join("", nList);
106             string LList = sList.Substring(0, j);
107             //Console.WriteLine(LList);
108             //LList没有问题了,但是key中还存在重复的值
109             string nkey = "";
110             foreach (char e in key)
111             {
112                 if (nkey.IndexOf(e) == -1)
113                 {
114                     nkey += e;
115                 }
116             }
117             NList = nkey + LList;
118             //Console.Write(NList);
119 
120             psd = psd.ToUpper();
121             char[] miwen1 = new char[psd.Length];
122             string miwen;
123             int i = 0;
124             if (xuanze == 1)
125             {
126                 foreach (char e in psd)
127                 {
128                     int m = List.IndexOf(e);
129                     string mm = NList.Substring(m, 1);
130                     miwen1[i] = Char.Parse(mm);
131                     i++;
132                 }
133                 miwen = string.Join("", miwen1);
134                 return miwen;
135             }
136             else
137             {
138                 foreach (char e in psd)
139                 {
140                     int m = NList.IndexOf(e);
141                     string mm = List.Substring(m, 1);
142                     miwen1[i] = Char.Parse(mm);
143                     i++;
144                 }
145                 miwen = string.Join("", miwen1);
146                 return miwen;
147             }
148         }
149         //维吉利亚
150         public string Virginia(int xuanze, string psd, string key)
151         {
152             string List = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
153             //先构建对应的秘钥
154             key = key.ToUpper();
155             char[] key1 = new char[key.Length];
156             int j = 0;
157             foreach (char e in key)
158             {
159                 key1[j] = e;
160                 j++;
161             }
162             j = 0;
163             ; string keywords = "";
164             for (int i = 0; i < psd.Length; i++)
165             {
166                 keywords += key1[j];
167                 j++;
168                 if (j == key.Length)
169                 {
170                     j = 0;
171                 }
172             }
173             psd = psd.ToUpper();
174             string miwen = "";
175             if (xuanze == 1)
176             {
177                 int m = 0, n = 0, k = 0, s = 0;
178                 foreach (char e in psd)
179                 {
180                     m = List.IndexOf(e);
181                     n = List.IndexOf(keywords.Substring(k, 1));
182                     s = (m + n) % 26;
183                     Console.Write(s);
184                     miwen += List.Substring(s, 1);
185                     k++;
186                 }
187                 return miwen;
188             }
189             else
190             {
191                 int i = 0;
192                 while (i < psd.Length)
193                 {
194                     int jj = i % key.Length;
195                     int x1 = List.IndexOf(key.Substring(jj, 1));
196                     int x2 = List.IndexOf(psd.Substring(i, 1));
197                     if (x2 < x1)
198                     {
199                         x2 += 26;
200                         miwen += List.Substring(x2 - x1, 1);
201                     }
202                     else
203                     {
204                         miwen += List.Substring(x2 - x1, 1);
205                     }
206                     i++;
207                 }
208                 return miwen;
209             }
210         }
211         //转换加密方法——密钥类型为int
212         public string ConvertingEncrypted(int xuanze, string psd, int key)
213         {
214             string npsd = "";
215             foreach (char e in psd)
216             {
217                 if (e != \' \')
218                 {
219                     npsd += e;
220                 }
221             }
222             int total;
223             if (npsd.Length % key == 0)
224             {
225                 total = npsd.Length / key;
226             }
227             else
228             {
229                 total = npsd.Length / key + 1;
230             }
231             //实现解密或加密过程
232             string[] password1 = new string[total];
233             Stack<char> stacks = new Stack<char>();
234             int x = 0, y = 0;
235             foreach (char e in npsd)
236             {
237                 stacks.Push(e);
238                 y++;
239                 if (y == key)
240                 {
241                     while (0 != stacks.Count)
242                     {
243                         password1[x] += stacks.Pop();
244                     }
245                     y = 0;
246                     x++;
247                 }
248             }
249             while (0 != stacks.Count)
250             {
251                 password1[x] += stacks.Pop();
252             }
253             //形成密文或原文
254             string miwen = "";
255             for (int i = 0; i < total; i++)
256             {
257                 miwen += password1[i];
258             }
259             return miwen;
260         }
261          //来一个重载的方法
262         public string ConvertingEncrypted(int xuanze, string psd, string key)
263         {
264        //去除原文/密文中的空格
265 string npsd = "";
266 foreach (char e in psd)
267             {
268                 if (e != \' \')
269                 {
270                     npsd += e;
271                 }
272             }
273             int total;
274             //做一个是否拆完的标记,之后会用到,否则会报超出索引
275             bool chujin = false;
276             if (npsd.Length % key.Length == 0)
277             {
278                 total = npsd.Length / key.Length;
279                 chujin = true;
280             }
281             else
282             {
283                 total = npsd.Length / key.Length + 1;
284                 chujin = false;
285             }
286             //按照密钥长度拆分原文
287             string[] password1 = new string[total];
288             int x = 0, y = 0;
289             foreach (char e in npsd)
290             {
291                 password1[x] += e;
292                 y++;
293                 if (y == key.Length)
294                 {
295                     y = 0;
296                     x++;
297                 }
298             }
299             //按照密钥字符串各个字符的顺序形成密文,有点晕,我觉得应该是这样的——这样要求密钥中不存在处重复的字符
300             string List = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
301             int[] shunxu = new int[key.Length];//记录密钥字母顺序数组(4321)
302             key = key.ToUpper();//将密钥全部转换成大写以便于一List进行比较
303             int i = 0;//声明一个标志值下面确定int数组的前进
304             foreach (char e in List)
305             {
306                 if (key.IndexOf(e) >= 0)
307                 {
308                     shunxu[i] = key.IndexOf(e);
309                     i++;
310                 }
311             }
312             int[] nshunxu = new int[key.Length];//加密时,处理顺序使adbc的0231变成0312
313             for (int ni = 0; ni < key.Length; ni++)
314             {
315                 for (int si = 0; si < key.Length; si++)
316                 {
317                     if (shunxu[si] == ni)
318                     {
319                         nshunxu[ni] = si;
320                         break;
321                     }
322                 }
323             }
324             if (xuanze==1) //加密时,处理顺序使adbc的0231变成0312
325             {
326                 shunxu = nshunxu;
327             }
328             if (!chujin)//如果没有除尽让最后一个数组剩余的字符为!
329             {
330                 int length = key.Length - password1[total - 1].Length;
331                 for (int xs = 0; xs < length; xs++)
332                 {
333                     password1[total - 1] += \'!\';
334                 }
335                 if(xuanze==2)//如果是解密最后一个没有整数拆分的要还原成加密状态
336                 {
337                     int iiis = 0;
338                     string mm = "";
339                     while (iiis < key.Length)
340                     {
341                         mm += password1[total-1].Substring(shunxu[iiis], 1);
342                         iiis++;
343                     }
344                     password1[total - 1] = mm;
345                 }
346             }
347             //加密解密操作核心,加密解密可以使用同一个算法
348             //将所有切分字符串按照密钥顺序排序
349             string[] password2 = new string[total];
350             int ii = 0;
351             while (ii < key.Length)
352             {
353                 for (int j = 0; j < total; j++)
354                 {
355                     password2[j] += password1[j].Substring(shunxu[ii], 1);
356                 }
357                 ii++;
358             }        
359             //将最后一个未除尽数组中的!删除
360             if (!chujin)
361             {
362                 string midpad = "";
363                 foreach (char e in password2[total - 1])
364                 {
365                     if (e != \'!\')
366                     {
367                         midpad += e;
368                     }
369                 }
370                 password2[total - 1] = midpad;
371             }
372             //将所=切分的字符串连接
373             string miwen = "";
374             for (int s = 0; s < total; s++)
375             {
376                 miwen += password2[s];
377             }
378             return miwen;
379   }
380 }

 

相关文章