最近、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_Initialise
basBlowfish.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 つのアルゴリズム間の同等性を求める私の検索が他の何かに依存している可能性があることを意味します)。