分类: C/C++
2009-12-22 11:39:40
ENIGMA密码系统研究
关于ENIGMA系统原理的介绍:http://blog.sina.com.cn/s/blog_4033131f010007wr.html
之所以要研究ENIGMA,是需要一种经济的数据通信加密方法,使用简便,系统开销小而又足够安全。
ENIGMA是一种复式替换序列密码体系,所谓序列密码,是指加密不分组,加密后的信息与加密前是等长的,简化了对通信buf的处理。它的强度并非很高。在商业通信中,完全不加密是危险的,过于复杂的加密也没必要。就像我们家庭,没必要像国库的安全级别,但也不能不锁门,我们通常使用的弹子锁,就是一种经济简便的安全措施,它早已被破解,但仍被广泛使用。
ENIGMA软件:
cat enigma1.c
#include
#include
#include
/*
* A one-rotor machine designed along the lines of Enigma
* but considerably trivialized.
*/
char *des_fcrypt();
char *crypt();
#define ECHO 010
#include
#define MASK 0377
/* 生成密码轮 */
static enigma1_setup(pw,salt,conn)
char *pw,*salt;
struct crypt_s *conn;
{
int ic, i, k, temp;
unsigned random,seed;
char *buf,buf1[20];
char *t1;
char *t2;
char *t3;
t1=conn->t1;
t2=conn->t2;
t3=conn->t3;
seed=ssh_crc32(pw,strlen(pw)); // seed=123;
buf=des_fcrypt(pw,salt,buf1);
for (i=0; i<13; i++)
seed = seed*buf[i] + i;
for(i=0;i
t1[i] = i;
t3[i] = 0;
}
for(i=0;i
seed = 5*seed + buf[i%13];
random = seed % 65521; //random(key);
/* 生成主编码轮 t1 */
k = ROTORSZ-1 - i;
ic = (random&MASK)%(k+1);
temp = t1[k];
t1[k] = t1[ic];
t1[ic] = temp;
/************************************************************************
* 生成反射板 反射板只要不重不漏的把各点两两连接起来?
* 可以随机的
************************************************************************/
if(t3[k]!=0) continue;
random >>= 8;
ic = (random&MASK) % k;
while(t3[ic]!=0) ic = (ic+1) % k;
t3[k] = ic;
t3[ic] = k;
}
/* t2为t1的逆 */
for(i=0;i
t2[t1[i]&MASK] = i;
}
void enigma1(pass, salt,string,len,conn)
char *pass,*string,*salt;
int len;
struct crypt_s *conn;
{
register char *p;
register int k;
int n1;
int n2;
char *t1,*t2,*t3;
if(!conn->pw||strncmp(conn->pw,pass,strlen(conn->pw))||strncmp(conn->salt,salt,2)) {
strncpy(conn->pw,pass,PWLEN);
strncpy(conn->salt,salt,SALTLEN);
conn->pw[PWLEN]=0;
conn->salt[SALTLEN]=0;
enigma1_setup(conn->pw,conn->salt,conn);
}
n2=n1 = 0;
p=string;
t1=conn->t1;
t2=conn->t2;
t3=conn->t3;
for(k=0;k
*p++ = t2[(t3[(t1[(*p+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
if(++n1==ROTORSZ) {
n1 = 0;
if(++n2==ROTORSZ) n2 = 0;
}
}
}
其中netcom.h中所需的内容:
#define ROTORSZ 256
#define PWLEN 16
#define SALTLEN 2
struct crypt_s {
char pw[PWLEN+1];
char salt[SALTLEN+1];
char t1[ROTORSZ]; /* pass.c: ROTORSZ*/
char t2[ROTORSZ];
char t3[ROTORSZ];
};
Demo程序:
#include
#include
extern void enigma1(char *key,char *salt,char *string,int len,struct crypt_s *enigma_s);
int main(int ac,char *av[])
{
char buf[131702];
char *key="agh57Dsar_~3C";
int len,i,len1;
struct crypt_s enis;
*enis.salt=0;
memset(buf,'A',sizeof(buf));
buf[sizeof(buf)-1]=0;
while(!ferror(stdin)) {
fgets(buf,sizeof(buf),stdin);
if(feof(stdin)) break;
TRIM(buf);
len=strlen(buf);
enigma1(key+2,key,buf,len,&enis);
len1=len>30?30:len;
for(i=0;i
printf("\n");
enigma1(key+2,key,buf,len,&enis);
printf("%.100s\n",buf);
}
return 0;
}
这是一个单轮带反射器的ENIGMA加密/解密机。256个位置的转轮,可加密二进制字节信息。反射器可以转动,等价一个编码轮,或称为反射轮。它的序列长度为64K,比ENIGMA的17576长。ENIGMA之所以被破解,源于它只有3个转轮,敌方得到了这3个转轮,又得知每次3个转轮的排列、起始位置、插线板设置,就完全破解了。
我们在SDBC中的使用,每次连接时动态生成密钥,密钥是非常随机的,等于有无数个转轮。如果要破解此密码,可以设法再生t1码轮和t3反射轮(这可是相当于长达512字节的密钥),这似乎是比较困难的。再有就是对密钥的强力攻击了,这个程序是采用crypt密钥生成转轮的,强度等同于crypt。当然,也可以采用强度更高的算法生成转轮。这个算法是否应该再增加一些转轮来提高强度?我认为没必要。它主要用于网络通信,数据包通常都不会超过64K,增加转轮不过是增加序列长度,超过64K的序列并无意义,却要大幅度增加开销。
SDBC使用这个程序,基本都属于短时效数据,经过长时间破解了,已经没有意义。对于长时效数据,用户应该采用其他方法自行加密。而SDBC是支持二进制数据传输的。