需要进行现实检查:我对 VB6 Blowfish bug 的分析是否正确?

发布于 2024-09-24 00:39:06 字数 1696 浏览 0 评论 0原文

最近我有理由比较 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],一个有符号的字符,符号扩展为0xffffff80 在与数据进行“或”运算之前。

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 管理代码附带的测试似乎都能正常工作(这可能意味着我对两种算法之间等效性的搜索可能取决于其他因素。)

Recently I had cause to compare Blowfish algorithms. I was comparing outputs from DI Management's library and PHP's mcrypt. I could not get them to agree in any way.

This led me on an interesting chase. According to this posting on Bruce Schneier's website, there was a sign extension bug in early versions of the Blowfish code, and it would seem that the DI Management code implements the pre-bug-report code.

The blurb in the bug report says, in part,

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;
        }
        ...
}

It chokes whenever the most significant bit
of key[j] is a '1'. For example, if key[j]=0x80,
key[j], a signed char, is sign extended to 0xffffff80
before it is ORed with data.

The equivalent code in the blf_Initialise function in basBlowfish.bas is

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

The bug-report suggests the following fix to the C code:

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

which I've implemented in VB6 as

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

In fact, I've written it so that both methods are used and then put in an assertion to check whether the values are the same or not, viz:

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

When aKey(j) contains 255, I get an assertion error.

Am I reading this situation aright? Is a sign-extension error occurring or am I seeing bugs that aren't there?

Strangely, the tests that come with the DI Management code appear to work correctly both with and without this change (which may mean that my search for equivalence between the two algorithms may depend on something else.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

临风闻羌笛 2024-10-01 00:39:06

如果我没看错(当然现在不能保证),那么你确实有一个错误。甚至可能是两个。请记住,在 C 中,类型转换的优先级高于按位运算。 C 代码将signed char 转换为unsigned long,然后用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。

If I'm reading that right (certainly not guaranteed at this hour), you do have a bug. Maybe even two. Remember that in C, type casts have a higher precendence than bitwise operations. The C code casts the signed char to an unsigned long before &ing it with 0xFF. Written verbosely:

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

However, the VB code you posted is equivalent to:

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

Hello, sign extension.

Also, did you mean to write this?

wDCheck = uw_ShiftLeftBy8(wDCheck) Or aKey(j)

Otherwise, you're setting wDCheck using the new value of wData.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文