3

最近我有理由比较 Blowfish 算法。我正在比较DI Management的库和 PHP 的mcrypt的输出。我无法让他们以任何方式同意。

这使我进行了一次有趣的追逐。根据Bruce Schneier 网站上的这篇帖子,Blowfish 代码的早期版本中存在符号扩展错误,并且似乎 DI 管理代码实现了预错误报告代码。

错误报告中的简介部分说,

bfinit(char *key,int keybytes)
{
    unsigned long data;
    ...
    j=0;
    ...
        data=0;
        for(k=0;k<4;k++){
            data=(data<<8)|key[j];/* choke*/
            j+=1;
            if(j==keybytes)
                j=0;
        }
        ...
}

每当 key[j] 的最高有效位是“1”时,它就会阻塞。例如,如果 key[j]=0x80,则 key[j],一个有符号字符,在与数据进行 OR 运算之前将符号扩展为 0xffffff80。

blf_InitialisebasBlowfish.bas中函数的等效代码是

   wData = &H0
    For k = 0 To 3
        wData = uw_ShiftLeftBy8(wData) Or aKey(j)
        j = j + 1
        If j >= nKeyBytes Then j = 0

错误报告建议对 C 代码进行以下修复:

data<<=8;
data|=(unsigned long)key[j]&0xff;

我在 VB6 中实现为

wData = uw_ShiftLeftBy8(wData)
wData = wData Or ( aKey(j) And &HFF )

事实上,我已经编写了它以便使用这两种方法,然后放入一个断言来检查值是否相同,即:

wData = uw_ShiftLeftBy8(wData)
wData = wData Or (aKey(j) And &HFF)
wDCheck = uw_ShiftLeftBy8(wData) Or aKey(j)
Debug.Assert wData = wDCheck

当 aKey(j) 包含 255 时,我得到一个断言错误。

我读对了这种情况吗?是出现符号扩展错误还是我看到不存在的错误?

奇怪的是,DI 管理代码附带的测试似乎在有和没有这种变化的情况下都能正常工作(这可能意味着我对两种算法之间等价性的搜索可能取决于其他东西。)

4

1 回答 1

2

如果我没看错(此时肯定不能保证),那么您确实有错误。甚至可能有两个。请记住,在 C 中,类型转换比按位操作具有更高的优先级。C 代码在用 0xFF &ing 之前将有符号字符转换为无符号字符。写得很详细:

data = (data << 8) | ( ((unsigned long)key[j]) & 0xFF );

但是,您发布的 VB 代码相当于:

wData = (wData << 8) | (unsigned long)(aKey[j] & 0xFF);

你好,签名扩展。

另外,你的意思是写这个吗?

wDCheck = uw_ShiftLeftBy8(wDCheck) Or aKey(j)

否则,您将使用 wData 的新值设置 wDCheck。

于 2010-09-16T08:12:48.413 回答