2010-09-16 14 views
3

Récemment, j'ai eu des raisons de comparer les algorithmes de Blowfish. Je comparais les sorties de la bibliothèque de DI Management et de mcrypt de PHP. Je ne pouvais pas les convaincre d'aucune façon.Besoin d'une vérification de la réalité: Mon analyse de ce bug VB6 Blowfish est-elle correcte?

Cela m'a mené sur une poursuite intéressante. Selon this posting sur le site Web de Bruce Schneier, il y avait un bogue d'extension de signe dans les premières versions du code de Blowfish, et il semblerait que le code de gestion DI implémente le code de pré-rapport de bogue.

Le texte de présentation dans le rapport de bogue dit, en partie,

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

Il étrangle chaque fois que le bit le plus significatif de [j] est un '1'. Par exemple, si la clé [j] = 0x80, la clé [j], un caractère signé, est étendu à 0xffffff80 avant qu'il soit avec des données.

Le code équivalent dans la fonction blf_Initialise dans basBlowfish.bas est

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

Le rapport de bug suggère le correctif suivant au code C:

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

que je l'ai mis en œuvre dans VB6 comme

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

En fait, je l'ai écrit pour que les deux méthodes sont utilisées puis mis dans une assertion de vérifier si les valeurs sont les mêmes ou non, à savoir:

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

Lorsque aKey (j) contient 255, I obtenir une erreur d'assertion.

Est-ce que je lis bien cette situation? Est-ce qu'une erreur d'extension de signe se produit ou est-ce que je vois des bogues qui ne sont pas là?

Étrangement, les tests qui viennent avec le code de gestion des DI semblent fonctionner correctement avec et sans ce changement (ce qui peut signifier que ma recherche d'équivalence entre les deux algorithmes peut dépendre de quelque chose d'autre.)

Répondre

2

Si Je lis bien (certainement pas garanti à cette heure), vous avez un bug. Peut-être même deux. Rappelez-vous que dans C, les conversions de type ont une plus grande précision que les opérations au niveau du bit. Le code C convertit le caractère signé en un signe non signé bien avant & avec 0xFF. Écrit verbeux:

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

Cependant, le code VB que vous avez envoyé équivalent à:

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

Bonjour, extension de signe.

Également, vouliez-vous écrire ceci?

wDCheck = uw_ShiftLeftBy8(wDCheck) Or aKey(j) 

Sinon, vous définissez wDCheck en utilisant la nouvelle valeur de wData.

+0

Eek! Yoicks! J'ai buggé mon propre bug !! – bugmagnet

+0

Juste une note - mon premier exemple avait besoin d'un ensemble supplémentaire de parenthèses. C'est corrigé maintenant. –