首页
社区
课程
招聘
关于blowfish弱密钥的疑问
发表于: 2004-12-15 15:39 5162

关于blowfish弱密钥的疑问

2004-12-15 15:39
5162
前几天学习blowfish算法,<<加密与解密2>>里有这样一段话:
----------------------------------------------------------------------
_WeakKey
功能:测试产生的box是否安全
参数:无
返回:AX=1 不安全;AX=0 安全
影响:AX, BX, CX, DX, SI, DI, 方向标志
描述:使用"_InitCrypt"函数产生用于加密的Boxes后,你应该用这个函数测试产生的Boxes是否安全。如果该key产生的Boxes不安全――可以被密码分析者通过分析Boxes得到key,那么,你应该采用另外一个key产生一个安全的Boxes用来加密。
-----------------------------------------------------------------------

这段话的意思是不是说:如果一个密钥不是WeakKey,那么分析key_pbox和key_sbox不能得到Key?

但是初始化密钥盒的过程就是一个加密过程,那么应该任何密钥都可以通过分析key_pbox得到
后来我试验了确实是可以,高手看看是否理解错了

blowfish加密是 16轮变换+末尾2次XOR

假设key_pbox是key_pbox[0]~key_pbox[17]

最后的key_pbox[16],key_pbox[17]显然可以求出来
只要把key_pbox[14],key_pbox[15]通过16轮变换后XOR即可

假设有两个DWORD x0,y0
通过第1轮后是x1,y1
通过第2轮后是x2,y2
通过第3轮后是x3,y3
....
通过第i轮后是xi,yi
....
通过第16轮后是x16,y16
通过末尾XOR得到密文x,y

key_pbox[i],key_pbox[i+1]都是由key_pbox[i-2],key_pbox[i-1]加密得到
也就是key_pbox[i],key_pbox[i+1]是key_pbox[i-2],key_pbox[i-1]的密文
这里相当于
x0=key_pbox[i]
y0=key_pbox[i+1]
x=key_pbox[i-2]
y=key_pbox[i-1]
设初始化以前的key_pbox[i],key_pbox[i+1]是A,B
那么只需要把x,y反向解密到AB后,x0,y0正向加密AB前,然后解方程就可以得到AB

设:
经过i轮后的值为x0,y0
经过i+1轮后的值为x1,y1
经过i+2轮后的值为x,y
初始化以前的key_pbox[i],key_pbox[i+1]是A,B

将key_pbox和sbox连接起来(也就是不需要key_sbox,把sbox当作key_sbox)

先调换x,y的值(因为每一轮结束都会做调换,再换一下就换回来了)
然后可以列出方程组<1>:
-------------------------
x1=A^x0
y1=F(x1)^y0
x=B^y1
y=F(x)^x1
-------------------------
F(x)是指blowfish中的key_sbox变换函数F(x),^表示XOR

x1,y1,A,B是未知量,但有4个方程,显然可解,消去x1,y1得:
-------------------------
x=B^y0^F(A^x0)
y=A^x0^F(x)
-------------------------

设:C=x0^A , D=y0^B,得:
-------------------------
x=F(x)^D
y=F(x)^C
-------------------------

显然可以解出C,D
-------------------------
C=F(x)^y
D=x^F(C)=x^F(F(x)^y)
-------------------------

代入C,D得
-------------------------
A=F(x)^y^x0
B=F(F(x)^y)^x^y0
-------------------------

这样就可以还原出A,B,逐步把所有的key_pbox还原就可以得到初始化以前的key_pbox
最后让key_pbox和pbox XOR一下就得到key了

后来写了程序验证一下,确实是可以

CBlowfish*bf=NULL;

DWORD F(DWORD x)
{
        return bf->F(x);
}

#define pbox(i) bf->bf_P[i] //(*(DWORD*)(bf->bf_P+i*4))

#define  lastxor(x,y) swap(x,y);y^=bf->bf_P[16];x^=bf->bf_P[17];
#define rlastxor(x,y) y^=bf->bf_P[16];x^=bf->bf_P[17];swap(x,y);
//times次数
void round_toward(DWORD x,DWORD y,DWORD*A,DWORD*B,int times)
{
        for(int i=0;i<times;i++)
        {
                x^=bf->bf_P[i];
                y^=F(x);
                swap(x,y);
        }
        *A=x;*B=y;
}
//正向通过times轮,加密

void round_backward(DWORD x,DWORD y,DWORD*A,DWORD*B,int times)
{

        for(int i=15;(15-i)<times;i--)
        {
                swap(x,y);
                y^=F(x);
                x^=bf->bf_P[i];
        }
        *A=x;*B=y;
}
//反向通过times轮,解密

void getkeys(DWORD x0,DWORD y0,DWORD x,DWORD y,DWORD*A,DWORD*B)
{
        swap(x,y);
        *A=F(x)^y^x0;
        *B=F(F(x)^y)^x^y0;
}
//解方程组<1>

bool Generate(BYTE*key_pbox,BYTE*key)
{
        bf=new CBlowfish(key_pbox);//自定义的构造函数,这个类是下载的,修改了一下

        DWORD x,y,x0,y0;
        round_toward(pbox(14),pbox(15),&x,&y,16);
        swap(x,y);
        pbox(16)^=x;
        pbox(17)^=y;
        swap(pbox(16),pbox(17)); //先还原pbox(16),pbox(17)

        int i;

        for(i=7;i>0;i--) //逐步还原每个key_pbox
        {
                x0=pbox((i-1)*2);y0=pbox((i-1)*2+1);

                x=pbox(i*2);y=pbox(i*2+1);

                rlastxor(x,y);

                round_toward(x0,y0,&x0,&y0,i*2);    //正向处理

                round_backward(x,y,&x,&y,15-i*2-1); //反向处理

                getkeys(x0,y0,x,y,&pbox(i*2),&pbox(i*2+1)); //解方程组<1>
        }

        x0=0;y0=0; //第一个要单独处理,因为密文是0,0
        x=pbox(i*2);y=pbox(i*2+1);
        rlastxor(x,y);
        round_toward(x0,y0,&x0,&y0,i*2);
        round_backward(x,y,&x,&y,15-i*2-1);
        getkeys(x0,y0,x,y,&pbox(i*2),&pbox(i*2+1));

        for(i=0;i<18;i++) //颠倒字节顺序,消除小端模式的影响
        {
                bf->bf_P[i]^=def_bf_P[i];
                bf->bf_P[i]=htonl(bf->bf_P[i]);
        }

        memcpy(key,bf->bf_P,18*4);

        delete bf;
        return true;
}

编译后程序在附件里
运行key to key_pbox.exe,在上面的框里输入"test for blowfish by DonQuixote[CCG][iPB]",点Generate,下面出现18*4个字节的key_pbox:

BF3B52DB920DD38F5695F76DA7EEBE2B152BF5E
CF72E8900416A94106A6BBB4ADC22C19E082D6E
7DCCCCD4991AE68869BB57FE4A92098444BBD53
96EF8A09B3086DDDB52A609B142

运行key_pbox to key.exe,在上面的框里输入这段key_pbox,点Generate,出现
"test for blowfish by DonQuixote[CCG][iPB]test for blowfish by DonQuixote"

显然 key_pbox <=> key 确实可以互推

附件:blowfish.rar

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 3686
活跃值: (1036)
能力值: (RANK:760 )
在线值:
发帖
回帖
粉丝
2
There are some description in "Applied Cryptography" by Schneier:

Serge Vaudenay examined Blowfish with known S-boxes and r rounds; a differential attack can recover the P-array with 28r + 1 chosen plaintexts [1568]. For certain weak keys that generate bad S-boxes (the odds of getting them randomly are 1 in 214), the same attack requires only 24r + 1 chosen plaintexts to recover the P-array. With unknown S-boxes this attack can detect whether a weak key is being used, but cannot determine what it is (neither the S-boxes nor the P-array). This attack only works against reduced-round variants; it is completely ineffective against 16-round Blowfish.

Of course, the discovery of weak keys is significant, even though they seem impossible to exploit. A weak key is one in which two entries for a given S-box are identical. There is no way to check for weak keys before doing the key expansion. If you are worried, you have to do the key expansion and check for identical S-box entries. I don’t think this is necessary, though.

I know of no successful cryptanalysis against Blowfish. To be safe, do not implement Blowfish with a reduced number of rounds.
2004-12-16 15:58
0
雪    币: 135
活跃值: (226)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
3
谢谢cnbragon的提示!
找到了这段话的中文描述(英文的完全看不懂:( )

WeakKey说的应该是从key_sbox推出key,我理解错了:)
2004-12-16 21:40
0
游客
登录 | 注册 方可回帖
返回
//