2017-04-27 4 views
-1

J'ai besoin de crypter les chaînes sous AES-128 pour mon application C/C++ en utilisant WinCrypt. Juste pour comprendre comment tout cela fonctionne, j'ai écrit un programme pour crypter une chaîne de 16 octets avec une clé AES de 16 octets (128 bits) mais cela ne fonctionne pas comme prévu (et les exemples MSDN n'aident pas) .Cryptage AES-128 en utilisant WinCrypt

Mon principal problème est avec l'appel à CryptEncrypt, je n'ai clairement comment utiliser les paramètres:

  • * pbData
  • * pdwDataLen
  • dwBufLen

Voici mon code:

#include <windows.h> 
#include <stdio.h> 
#include <wincrypt.h> 
#define ENCRYPT_ALGORITHM CALG_AES_128 

int main() 
{ 

    HCRYPTPROV hCryptProv; 
    HCRYPTKEY hKey; 

//--------------------------------------------------------------- 
// Get the handle to the provider. 
if(CryptAcquireContext(
    &hCryptProv, 
    NULL, 
    NULL, //MS_ENH_RSA_AES_PROV 
    PROV_RSA_AES, 
    0)) 
{ 
    printf("A cryptographic provider has been acquired. \n"); 
} 
else 
{ 
    printf("Error during CryptAcquireContext!\n"); 
    exit(1); 
} 


//--------------------------------------------------------------- 
// Create a random session key. 

if(CryptGenKey(
      hCryptProv, 
      ENCRYPT_ALGORITHM, 
      CRYPT_EXPORTABLE, //KEYLENGTH | CRYPT_EXPORTABLE, 
      &hKey)) 
{ 
     printf("A session key has been created.\n"); 
} 
else 
{ 
      printf("Error during CryptGenKey.\n"); 
      exit(1); 
} 
} 

char text_test [] = "abcdabcdabcdabcd"; 
    DWORD text_len = strlen(text_test); 

    printf("PlainText: %s\n",text_test); 
    printf("Buf Len: %d\n",text_len); 

    if (!CryptEncrypt(hKey, 
        NULL, // hHash = no hash 
        1, // Final 
        0,  // dwFlags 
        &text_test, //*pbData 
        &text_len, //*pdwDataLen 
        32)) {  //dwBufLen 
    printf("Encryption failed\n"); 
    } 

    printf("CipherText: %s\n",text_test); 
    printf("Len: %d\n",text_len); 

    if (!CryptDecrypt(hKey, 
        NULL, // hHash = no hash 
        1, // Final 
        0,  // dwFlags 
        &text_test, 
        &text_len)) { 
    printf("Decryption failed\n"); 
    } 

    printf("PlainText: %s\n",text_test); 
    printf("Len: %d\n",text_len); 
. 
. 
. 
CryptDestroyKey(hKey) 
. 
. 
CryptReleaseContext(hCryptProv, 0) 
. 

La sortie dans le cmd est:

enter image description here

Quelqu'un peut-il me expliquer pourquoi la chaîne décryptée est plus longue et qui est l'utilisation correcte de ce trois paramètres de CryptEncrypt? J'ai mis la dernière valeur à 32 parce qu'après quelques essais et erreurs, c'était la seule valeur qui a fait fonctionner ce truc. Aide s'il vous plait et merci d'avance!

+0

je pense que le reste de la chaîne décryptée est le remplissage – zapredelom

+0

@zapredelom oui, je pense qu'il pourrait être padding, mais je ne sais pas comment utiliser correctement les paramètres de CryptEncrypt. –

Répondre

1

Je suis nouveau à la cryptographie aussi, mais ce code de here pourrait avoir votre solution:

// This acts as both the length of bytes to be encoded (on input) and the 
    // number of bytes used in the resulting encrypted data (on output). 
    DWORD length = kAesBytes128; 
    if (!CryptEncrypt(hKey, 
        NULL, // hHash = no hash 
        true, // Final 
        0,  // dwFlags 
        reinterpret_cast<BYTE*>(encrypted->data()), 
        &length, 
        encrypted->length())) { 
    throw std::runtime_error("Encryption failed"); 
    } 

    // See comment above. 
    encrypted->chop(length - kAesBytes128); 

Ou je pourrais avoir un travail à partir d'un code de projet similaire en utilisant Crypto de

+0

Merci mais j'ai vu cet article avant de poster ma question. Dans cet exemple, je ne comprends pas les paramètres * pbData ni dwBufLen. Je ne sais pas comment les utiliser dans mon code. –

+0

https://msdn.microsoft.com/en-us/library/windows/desktop/aa379924(v=vs.85).aspx est le document API 'pbData - Un pointeur vers un tampon qui contient le texte en clair à être chiffré. Le texte en clair dans ce tampon est remplacé par le texte chiffré créé par cette fonction. » ' dwBufLen - Spécifie la taille totale, en octets, du tampon d'entrée pbData. » Cela me semble évident. – PatrickB

+0

En outre, AES est un chiffrement par bloc, cette restriction s'applique: 'Lorsqu'un chiffrement par bloc est utilisé, cette longueur de données doit être un multiple de la taille du bloc sauf s'il s'agit de la dernière section à chiffrer et que le paramètre Final est TRUE .' – PatrickB

0

Il est le rembourrage. Par défaut, vous aurez une quantité égale de remplissage insérée comme les octets que vous chiffrez. Ignore les 16 derniers octets. Les 16 premiers octets sont ce que vous voulez.