3

最近、Blowfish アルゴリズムを比較する機会がありました。DI Managementのライブラリと PHP のmcryptの出力を比較していました。私は彼らに同意してもらうことができませんでした。

これは私を興味深い追跡に導きました。Bruce Schneier の Web サイトへのこの投稿によると、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 の場合、signed char である 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 管理コードに付属するテストは、この変更の有無にかかわらず正しく動作するように見えます (これは、2 つのアルゴリズム間の同等性を求める私の検索が他の何かに依存している可能性があることを意味します)。

4

1 に答える 1

2

私がその通りに読んでいれば (確かに現時点では保証されていません)、バグがあります。たぶん2つ。C では、型キャストはビット演算より優先度が高いことに注意してください。C コードは、signed char を unsigned にキャストしてから、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 に答える