Недавно у меня была причина сравнить алгоритмы Blowfish. Я сравнивал выходные данные из библиотеки DI Management и PHP mcrypt . Я никак не мог заставить их согласиться.
Это привело меня к интересной погоне. Согласно этой публикации на веб-сайте Брюса Шнайера, в ранних версиях кода 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;
}
...
}
Он задыхается всякий раз, когда самый значимый бит
ключа [j] - это «1». Например, если ключ [j] = 0x80,
ключ [j], символ со знаком, знак расширяется до 0xffffff80
прежде чем он ORed с данными.
Эквивалентный код в функции 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 Management, работают корректно как с этим изменением, так и без него (это может означать, что мой поиск эквивалентности между этими двумя алгоритмами может зависеть от чего-то еще).