Нужна проверка реальности: мой анализ этой ошибки VB6 Blowfish правильный? - PullRequest
3 голосов
/ 16 сентября 2010

Недавно у меня была причина сравнить алгоритмы 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, работают корректно как с этим изменением, так и без него (это может означать, что мой поиск эквивалентности между этими двумя алгоритмами может зависеть от чего-то еще).

1 Ответ

2 голосов
/ 16 сентября 2010

Если я читаю это правильно (конечно, не гарантировано в этот час), у вас есть ошибка.Может быть, даже два.Помните, что в C приведение типов имеет более высокий приоритет, чем побитовые операции.Код C преобразует подписанный символ в неподписанный задолго до того, как 0xFF.Написано многословно:

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

Однако отправленный вами код VB эквивалентен:

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

Привет, расширение знака.

Кроме того, вы хотели написатьthis?

wDCheck = uw_ShiftLeftBy8(wDCheck) Or aKey(j)

В противном случае вы устанавливаете wDCheck, используя новое значение wData.

...