最近我有理由比较Blowfish算法。我正在比较DI Management的库和PHP的mcrypt的输出。我无法以任何方式让他们同意。
这让我有了一个有趣的追逐。根据Bruce Schneier网站上的this posting,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],一个带符号的char,符号扩展为0xffffff80 在对数据进行OR运算之前。
basBlowfish.bas中blf_Initialise
函数中的等效代码是
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管理代码附带的测试似乎在有或没有这种变化的情况下都能正常工作(这可能意味着我对两种算法之间的等价性的搜索可能依赖于别的东西。)
答案 0 :(得分:2)
如果我正确地阅读(当然不能保证在这个时候),你确实有一个错误。也许甚至两个。请记住,在C中,类型转换具有比按位操作更高的优先级。 C代码在使用0xFF之前将签名的char转换为unsigned。写得很冗长:
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。