ENIGMA密码机程序

ENIGMA是一种复式替换序列密码体系,所谓序列密码,是指加密不分组,加密后的信息与加密前是等长的,简化了对通信buf的处理。它的强度并非很高。在商业通信中,完全不加密是危险的,过于复杂的加密也没必要。就像我们家庭,没必要像国库的安全级别,但也不能不锁门,我们通常使用的弹子锁,就是一种经济简便的安全措施。。

直到第一次世界大战结束为止,所有密码都是使用手工来编码的。直接了当地说,就是铅笔加纸的方式。在我国,邮电局电报编码和译码直到很晚(大概是上个世纪八十年代初)还在使用这种手工方法。手工编码的方式给使用密码的一方带来很多的不便。首先,这使得发送信息的效率极其低下。明文(就是没有经过加密的原始文本)必须由加密员人工一个一个字母地转换为密文。考虑到不能多次重复同一种明文到密文的转换方式(这很容易使敌人猜出这种转换方式),和民用的电报编码解码不同,加密人员并不能把转换方式牢记于心。转换通常是采用查表的方法,所查表又每日不同,所以解码速度极慢。而接收密码一方又要用同样的方式将密文转为明文。其次,这种效率的低下的手工操作也使得许多复杂的保密性能更好的加密方法不能被实际应用,而简单的加密方法根本不能抵挡解密学的威力。
 
解密一方当时正值春风得意之时,几百年来被认为坚不可破的维吉耐尔(Vigenere)密码和它的变种也被破解。而无线电报的发明,使得截获密文易如反掌。无论是军事方面还是民用商业方面都需要一种可靠而又有效的方法来保证通讯的安全。
 
1918年,德国发明家亚瑟·谢尔比乌斯(ArthurScherbius)和他的朋友理查德·里特(RichardRitter)创办了谢尔比乌斯和里特公司。这是一家专营把新技术转化为应用方面的企业,很象现在的高新技术公司,利润不小,可是风险也很大。谢尔比乌斯负责研究和开发方面,紧追当时的新潮流。他曾在汉诺威和慕尼黑研究过电气应用,他的一个想法就是要用二十世纪的电气技术来取代那种过时的铅笔加纸的加密方法。
谢尔比乌斯发明的加密电子机械名叫ENIGMA,在以后的年代里,它将被证明是有史以来最为可靠的加密系统之一,而对这种可靠性的盲目乐观,又使它的使用者遭到了灭顶之灾。这是后话,暂且不提。
 
ENIGMA看起来是一个装满了复杂而精致的元件的盒子。不过要是我们把它打开来,就可以看到它可以被分解成相当简单的几部分。下面的图是它的最基本部分的示意图,我们可以看见它的三个部分:键盘、转子和显示器。
 
在上面ENIGMA的照片上,我们看见水平面板的下面部分就是键盘,一共有26个键,键盘排列接近我们现在使用的计算机键盘。为了使消息尽量地短和更难以破译,空格和标点符号都被省略。在示意图中我们只画了六个键。实物照片中,键盘上方就是显示器,它由标示了同样字母的26个小灯组成,当键盘上的某个键被按下时,和此字母被加密后的密文相对应的小灯就在显示器上亮起来。同样地,在示意图上我们只画了六个小灯。在显示器的上方是三个转子,它们的主要部分隐藏在面板之下,在示意图中我们暂时只画了一个转子。
 
键盘、转子和显示器由电线相连,转子本身也集成了6条线路(在实物中是26条),把键盘的信号对应到显示器不同的小灯上去。在示意图中我们可以看到,如果按下a键,那么灯B就会亮,这意味着a被加密成了B。同样地我们看到,b被加密成了A,c被加密成了D,d被加密成了F,e被加密成了E,f被加密成了C。于是如果我们在键盘上依次键入cafe(咖啡),显示器上就会依次显示DBCE。这是最简单的加密方法之一,把每一个字母都按一一对应的方法替换为另一个字母,这样的加密方式叫做“简单替换密码” 。

 

 

  1  cat enigma1.c
  2 
  3 #include <stdio.h>
  4 
  5 #include <netcom.h>
  6 
  7 #include <crc32.h>
  8 
  9 /*
 10 
 11  *      A one-rotor machine designed along the lines of Enigma
 12 
 13  *      but considerably trivialized.
 14 
 15  */
 16 
 17 char *des_fcrypt();
 18 
 19 char *crypt();
 20 
 21 #define ECHO 010
 22 
 23 #include <stdio.h>
 24 
 25 #define MASK 0377
 26 
 27  
 28 
 29  
 30 
 31 /* 生成密码轮 */   
 32 
 33 static enigma1_setup(pw,salt,conn)
 34 
 35 char *pw,*salt;
 36 
 37 struct crypt_s *conn;
 38 
 39 {
 40 
 41 int ic, i, k, temp;
 42 
 43 unsigned random,seed;
 44 
 45 char *buf,buf1[20];
 46 
 47 char    *t1;
 48 
 49 char    *t2;
 50 
 51 char    *t3;
 52 
 53  
 54 
 55         t1=conn->t1;
 56 
 57         t2=conn->t2;
 58 
 59         t3=conn->t3;
 60 
 61         seed=ssh_crc32(pw,strlen(pw)); // seed=123;
 62 
 63  
 64 
 65         buf=des_fcrypt(pw,salt,buf1);
 66 
 67         for (i=0; i<13; i++)
 68 
 69                 seed = seed*buf[i] + i;
 70 
 71         for(i=0;i<ROTORSZ;i++) {
 72 
 73                 t1[i] = i;
 74 
 75                 t3[i] = 0;
 76 
 77         }
 78 
 79         for(i=0;i<ROTORSZ;i++) {
 80 
 81                 seed = 5*seed + buf[i%13];
 82 
 83                 random = seed % 65521;  //random(key);
 84 
 85 /* 生成主编码轮 t1 */
 86 
 87                 k = ROTORSZ-1 - i;
 88 
 89                 ic = (random&MASK)%(k+1);
 90 
 91  
 92 
 93                 temp = t1[k];
 94 
 95                 t1[k] = t1[ic];
 96 
 97                 t1[ic] = temp;
 98 
 99 /************************************************************************
100 
101  * 生成反射板 反射板只要不重不漏的把各点两两连接起来?
102 
103  * 可以随机的  
104 
105  ************************************************************************/
106 
107                 if(t3[k]!=0) continue;
108 
109                 random >>= 8;
110 
111                 ic = (random&MASK) % k;
112 
113                 while(t3[ic]!=0) ic = (ic+1) % k;
114 
115                 t3[k] = ic;
116 
117                 t3[ic] = k;
118 
119         }
120 
121 /* t2为t1的逆 */
122 
123         for(i=0;i<ROTORSZ;i++)
124 
125                 t2[t1[i]&MASK] = i;
126 
127 }
128 
129  
130 
131 void enigma1(pass, salt,string,len,conn)
132 
133 char *pass,*string,*salt;
134 
135 int len;
136 
137 struct crypt_s *conn;
138 
139 {
140 
141 register char *p;
142 
143 register int  k;
144 
145 int  n1;
146 
147 int n2;
148 
149 char *t1,*t2,*t3;
150 
151  
152 
153         if(!conn->pw||strncmp(conn->pw,pass,strlen(conn->pw))||strncmp(conn->salt,salt,2)) {
154 
155                 strncpy(conn->pw,pass,PWLEN);
156 
157                 strncpy(conn->salt,salt,SALTLEN);
158 
159                 conn->pw[PWLEN]=0;
160 
161                 conn->salt[SALTLEN]=0;
162 
163                 enigma1_setup(conn->pw,conn->salt,conn);
164 
165         }
166 
167         n2=n1 = 0;
168 
169         p=string;
170 
171         t1=conn->t1;
172 
173         t2=conn->t2;
174 
175         t3=conn->t3;
176 
177  
178 
179         for(k=0;k<len;k++){
180 
181                 *p++ = t2[(t3[(t1[(*p+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
182 
183                 if(++n1==ROTORSZ) {
184 
185                         n1 = 0;
186 
187                         if(++n2==ROTORSZ) n2 = 0;
188 
189                 }
190 
191         }
192 
193 }
194 
195 其中netcom.h中所需的内容:
196 
197 #define ROTORSZ 256
198 
199 #define PWLEN 16
200 
201 #define SALTLEN 2
202 
203 struct crypt_s {
204 
205         char    pw[PWLEN+1];
206 
207         char    salt[SALTLEN+1];
208 
209         char t1[ROTORSZ];               /* pass.c: ROTORSZ*/
210 
211         char t2[ROTORSZ];
212 
213         char t3[ROTORSZ];
214 
215 };
216 
217  
218 
219 Demo程序:
220 
221 #include <stdio.h>
222 
223 #include<netcom.h>
224 
225  
226 
227 extern void enigma1(char *key,char *salt,char *string,int len,struct crypt_s *enigma_s);
228 
229  
230 
231 int main(int ac,char *av[])
232 
233 {
234 
235 char buf[131702];
236 
237 char *key="agh57Dsar_~3C";
238 
239 int len,i,len1;
240 
241 struct crypt_s enis;
242 
243  
244 
245         *enis.salt=0;
246 
247         memset(buf,'A',sizeof(buf));
248 
249         buf[sizeof(buf)-1]=0;
250 
251         while(!ferror(stdin)) {
252 
253                 fgets(buf,sizeof(buf),stdin);
254 
255                 if(feof(stdin)) break;
256 
257                 TRIM(buf);
258 
259                 len=strlen(buf);
260 
261                 enigma1(key+2,key,buf,len,&enis);
262 
263                 len1=len>30?30:len;
264 
265                 for(i=0;i<len1;i++) printf("%02X ",buf[i]&255);
266 
267                 printf("\n");
268 
269                 enigma1(key+2,key,buf,len,&enis);
270 
271                 printf("%.100s\n",buf);
272 
273  
274 
275         }
276 
277         return 0;
278 
279 }
280 
281  

 

 

这是一个单轮带反射器的ENIGMA加密/解密机。256个位置的转轮,可加密二进制字节信息。反射器可以转动,等价一个编码轮,或称为反射轮。它的序列长度为64K,比ENIGMA的17576长。ENIGMA之所以被破解,源于它只有3个转轮,敌方得到了这3个转轮,又得知每次3个转轮的排列、起始位置、插线板设置,就完全破解了。

我们在SDBC中的使用,每次连接时动态生成密钥,密钥是非常随机的,等于有无数个转轮。如果要破解此密码,可以设法再生t1码轮和t3反射轮(这可是相当于长达512字节的密钥),这似乎是比较困难的。再有就是对密钥的强力攻击了,这个程序是采用crypt密钥生成转轮的,强度等同于crypt。当然,也可以采用强度更高的算法生成转轮。这个算法是否应该再增加一些转轮来提高强度?我认为没必要。它主要用于网络通信,数据包通常都不会超过64K,增加转轮不过是增加序列长度,超过64K的序列并无意义,却要大幅度增加开销。

SDBC使用这个程序,基本都属于短时效数据,经过长时间破解了,已经没有意义。对于长时效数据,用户应该采用其他方法自行加密。而SDBC是支持二进制数据传输的。

转载于:https://www.cnblogs.com/Yinxinghan/p/ENIGMA_Pasword_Machine.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值