2010-02-09 16 views
0

J'essaie d'utiliser les fonctions Microsoft 'Crypt ...' pour générer une clé de hachage MD5 à partir des données ajoutées à l'objet de hachage. J'essaie également d'utiliser 'CryptSetHashParam' pour définir l'objet de hachage à une valeur de hachage particulière avant d'y ajouter des données. Selon la documentation Microsoft (si je l'interprète correctement), vous devriez être capable de le faire en créant un hachage en double de l'objet original, utilisez la fonction 'CryptGetHashParam' pour récupérer la taille du hachage puis utilisez 'CryptSetHashParam 'sur l'objet original pour définir la valeur de hachage en conséquence. Je suis conscient qu'après avoir utilisé 'CryptGetHashParam' vous ne pouvez pas ajouter de données supplémentaires à un objet de hachage (c'est pourquoi je pensais que vous deviez créer un doublon), mais je ne peux pas ajouter de données à l'objet de hachage original ou au doublon objet de hachage après avoir utilisé 'CryptGetHashParam' (comme prévu), ou 'CryptSetHashParam' (que je ne m'attendais pas).Pourquoi, après avoir utilisé 'CryptSetHashParam', est-ce que je ne peux plus ajouter de données à mon objet de hachage MD5?

Voici des extraits de code de la classe, je suis en train d'écrire et un exemple de la façon dont je me sers des fonctions de classe:

Le résultat que je reçois après l'exécution du code est:

« fonction AddDataToHash a échoué - Errorcode : 2148073484. ", qui se traduit par:" Hash non valide pour une utilisation dans un état spécifié. ".

J'ai essayé de nombreuses façons d'essayer de faire fonctionner comme prévu, mais le résultat est toujours le même. J'accepte que je fais quelque chose de mal, mais je ne vois pas ce que je fais de mal. Des idées s'il vous plaît?

INITIALISATION DE CONSTRUCTEUR DE CLASSE.

CAuthentication::CAuthentication() 

{ 

    m_dwLastError = ERROR_SUCCESS; 

    m_hCryptProv = NULL; 

    m_hHash = NULL; 

    m_hDuplicateHash = NULL; 

    if(!CryptAcquireContext(&m_hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET)) 

    { 
     m_dwLastError = GetLastError(); 

     if (m_dwLastError == 0x80090016) 
     { 
      if(!CryptAcquireContext(&m_hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET)) 
      { 
       m_dwLastError = GetLastError(); 

       m_hCryptProv = NULL; 
      } 
     } 
    } 

    if(!CryptCreateHash(m_hCryptProv, CALG_MD5, 0, 0, &m_hHash)) 
    { 
     m_dwLastError = GetLastError(); 

     m_hHash = NULL; 
    } 
} 

FONCTION UTILISÉE POUR RÉGLER LA VALEUR DE HACHAGE DE L'OBJET HASH.

bool CAuthentication::SetHashKeyString(char* pszKeyBuffer) 

{ 

    bool bHashStringSet = false; 

    DWORD dwHashSize = 0; 
    DWORD dwHashLen = sizeof(DWORD); 

    BYTE byHash[DIGITAL_SIGNATURE_LENGTH/2]={0}; 

    if(pszKeyBuffer != NULL && strlen(pszKeyBuffer) == DIGITAL_SIGNATURE_LENGTH) 
    { 
     if(CryptDuplicateHash(m_hHash, NULL, 0, &m_hDuplicateHash)) 
     { 
      if(CryptGetHashParam(m_hDuplicateHash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&dwHashSize), &dwHashLen, 0)) 
      {   
       if (dwHashSize == DIGITAL_SIGNATURE_LENGTH/2) 
       { 
        char*pPtr = pszKeyBuffer; 

        ULONG ulTempVal = 0; 

        for(ULONG ulIdx = 0; ulIdx < dwHashSize; ulIdx++) 
        { 
         sscanf(pPtr, "%02X", &ulTempVal); 

         byHash[ulIdx] = static_cast<BYTE>(ulTempVal); 

         pPtr+= 2; 
        } 

        if(CryptSetHashParam(m_hHash, HP_HASHVAL, &byHash[0], 0)) 
        { 
         bHashStringSet = true; 
        } 
        else 
        { 
         pszKeyBuffer = ""; 
         m_dwLastError = GetLastError(); 
        } 
       } 
      } 
      else 
      { 
       m_dwLastError = GetLastError(); 
      } 
     } 
     else 
     { 
      m_dwLastError = GetLastError(); 
     } 
    } 

    if(m_hDuplicateHash != NULL) 
    { 
     CryptDestroyHash(m_hDuplicateHash); 
    } 

    return bHashStringSet; 
} 

FONCTION UTILISÉE POUR AJOUTER DES DONNÉES DE HACHAGE.

bool CAuthentication::AddDataToHash(BYTE* pbyHashBuffer, ULONG ulLength) 

{ 

    bool bHashDataAdded = false; 

    if(CryptHashData(m_hHash, pbyHashBuffer, ulLength, 0)) 
    { 
     bHashDataAdded = true; 
    } 
    else 
    { 
     m_dwLastError = GetLastError(); 
    } 

    return bHashDataAdded; 
} 

MAIN USAGE DE CLASSE FONCTION:

CAuthentication auth; 

.....

auth.SetHashKeyString("0DD72A4F2B5FD48EF70B775BEDBCA14C"); 

.....

if(!auth.AddDataToHash(pbyHashBuffer, ulDataLen)) 

{ 

    TRACE("CryptHashData function failed - Errorcode: %lu.\n", auth.GetAuthError()); 
} 

Répondre

1

Vous ne pouvez pas le faire parce que cela n'a aucun sens. CryptGetHashParam avec l'option HP_HASHVAL finalise le hachage, donc il n'y a aucun moyen d'y ajouter des données. Si vous voulez "fourchonner" le hachage afin de pouvoir le finaliser à un moment donné et y ajouter des données, vous devez dupliquer l'objet de hachage avant la finalisation. Ensuite, vous ajoutez les données à l'un des objets de hachage et finalisez l'autre. Par exemple, vous pouvez le faire si vous souhaitez enregistrer un hachage cumulatif après 1024 octets d'un flux de données. Vous ne devez pas appeler CryptSetHashParam sur l'objet de hachage auquel vous continuez d'ajouter des données. CryptSetHashParam avec l'option HP_HASHVAL est un hack brutal pour surmonter une limitation dans le CryptoAPI.

Le CryptoAPI signera seulement un objet de hachage, donc si vous voulez signer des données qui ont été hachées ou générées en dehors de CAPI, vous devez le "brouiller" dans un objet de hachage.

EDIT:
En fonction de votre commentaire, je pense que vous cherchez un moyen de sérialiser l'objet de hachage. Je ne trouve aucune preuve que CryptoAPI supporte cela. Il existe cependant des alternatives qui sont essentiellement des variantes de mon exemple "1024 octets" ci-dessus. Si vous êtes en train de hacher une séquence de fichiers, vous pouvez simplement calculer et enregistrer le hachage de chaque fichier. Si vous avez vraiment besoin de le réduire à une valeur, vous pouvez calculer un hachage modifié où le premier morceau de données que vous avez pour le fichier i est le hash finalisé pour les fichiers 0, 1, 2, ..., i -1. Alors:
H-1 = empty,
Hi = MD5 (Hi-1 || filei)

Comme vous allez le long, vous pouvez enregistrer la dernière valeur calculée avec succès Hi. En cas d'interruption, vous pouvez redémarrer dans le fichier i+1. Notez que, comme tout résumé de message, ce qui précède est complètement sensible à la fois à l'ordre et au contenu. C'est quelque chose à considérer sur un système de fichiers changeant dynamiquement. Si des fichiers peuvent être ajoutés ou modifiés pendant l'opération de hachage, la signification de la valeur de hachage sera affectée. Il pourrait être rendu sans signification. Vous pouvez être certain que la séquence des fichiers et des fichiers que vous êtes en train de hacher est gelée pendant toute la durée du hachage.

+0

Je suppose que je devrais expliquer pourquoi j'essaie d'initialiser un objet de hachage avec une valeur de hachage de départ prédéfinie pour mettre en évidence le problème que j'essaie de surmonter. Les données que je déteste proviennent d'un NAS contenu dans des centaines de fichiers potentiels. Après avoir haché les données dans chaque fichier, je cherche à conserver localement le hachage MD5 de sorte que si l'application de hachage subit une interruption et soit redémarrée, un nouvel objet de hachage est initialisé avec la valeur de hachage au point d'interruption empêchant ainsi commencer à hacher à partir du début du NAS à nouveau. Y a-t-il un moyen de faire cela? –

+0

Si aucun fichier supplémentaire n'a été ajouté au NAS et que le hachage MD5 a été effectué sur toutes les données contenues dans tous les fichiers sans interruption, la valeur de hachage résultante ne serait-elle pas différente si toutes les données étaient hachées à nouveau, mais cette fois avec des interruptions? rencontré. Si j'ai interprété correctement ce qui a été dit auparavant, vous suggérez que la valeur de hachage qui a été calculée avant une interruption soit introduite dans l'objet de hachage avant les données de fichier suivantes. Cela ne se traduirait-il pas par un hachage calculé sur les données de hachage, résultant en une valeur de hachage finale différente de celle du hachage ininterrompu? –

+0

Vous gardez une trace du dernier fichier haché avec succès. Lorsqu'une interruption se produit au milieu du fichier de hachage i + 1, il vous suffit de rejeter le résultat partiel et de recommencer en recalculant MD5 (H_i || fichier_ {i + 1}) = H_ {i + 1}. –