2014-12-10 10 views
0

У меня есть некоторые проблемы. Мне нужно создать и экспортировать симметричный ключ с использованием CryptoAPI.Как экспортировать симметричный ключ AES cryptoapi

 if(CryptAcquireContext(&hCryptProv_AES, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) 
    { 
     _tprintf(
      TEXT("A cryptographic provider has been acquired. \n")); 
    } 
    else 
    { 
      DWORD d = GetLastError(); 
      std::cout<<""; 
      return -1; 
    } 

    if (!CryptGenKey(hCryptProv_AES,CALG_AES_256,CRYPT_EXPORTABLE,&hSessionKey_AES)) 
     { 
      DWORD d = GetLastError(); 
      std::cout<<""; 
      return -1; 
     } 
    else 
    { 
     std::cout<<"OK"; 
    } 

    // Export key 
    BYTE keybuf[ 1024 ], buffer[ 1024 ]; 
    DWORD i, keylen = sizeof(buffer); 

    struct ekb 
    { 
     PUBLICKEYSTRUC hdr; 
     ALG_ID     algId; 
     BYTE     key[1]; 
    } *encKey = (struct ekb *)buffer; 

    bool bbb = CryptExportKey(hSessionKey_AES, NULL, SIMPLEBLOB, 0, (BYTE *)encKey, &keylen); 
    DWORD f = GetLastError(); 

но не могу взять ключ AES. Как я могу исправить эту проблему, пожалуйста, помогите. Как я могу получить ключ AES?

UPDATE Например, я использую следующий код и могу получить открытый ключ RSA.

char * base_txt = "Test text"; 
    char * enc_text = ""; 


    if(CryptAcquireContext(&hCryptProv_RSA, NULL, MS_ENHANCED_PROV , PROV_RSA_FULL, 0)) 
    { 
     _tprintf(
      TEXT("A cryptographic provider has been acquired. \n")); 
    } 
    else 
    { 
      DWORD d = GetLastError(); 
      std::cout<<""; 
      return -1; 
    } 

    if (!CryptGenKey(hCryptProv_RSA,AT_KEYEXCHANGE,1024<<16,&hSessionKey)) 
     { 
      DWORD d = GetLastError(); 
      std::cout<<""; 
      return -1; 
     } 

    RSAPubKey1024 key; 
    DWORD dwLen=sizeof(RSAPubKey1024); 



    // Export key 
    bool bb = CryptExportKey(hSessionKey,NULL,PUBLICKEYBLOB,0,(BYTE *)&key,&dwLen); 

UPDATE 2 После экспорта импортировать ключ и попробовать шифровать и дешифровать

HCRYPTPROV hCryptProv_AES22; 
    if (CryptAcquireContext(&hCryptProv_AES22, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) 
    { 
     printf("A cryptographic provider has been acquired.\r\n"); 
    } 
    else 
    { 
     DWORD d = GetLastError(); 
     return -1; 
    } 
    int iii = CryptImportKey(hCryptProv_AES22,(BYTE *)&exportKey_AES,keylen,NULL,NULL,&hSessionKey_AES2); 

    if(CryptSetKeyParam(hSessionKey_AES2,KP_IV, exportKey_AES, 0)) 
    { 
     BYTE encryptedMessage[1024]; 
     const char * message = "Decryption Works -- using multiple blocks"; 
     BYTE messageLen = (BYTE)strlen(message); 
     memcpy(encryptedMessage, message, messageLen); 
     DWORD encryptedMessageLen = messageLen; 
     CryptEncrypt(hSessionKey_AES2, NULL, TRUE, 0, encryptedMessage, &encryptedMessageLen, sizeof(encryptedMessage));  
     CryptDecrypt(hSessionKey_AES2,NULL,TRUE,0,encryptedMessage, &encryptedMessageLen); 

    } 
+0

Почему, на ваш взгляд, вы не можете поставить ключ AES? Возвращает ли 'CryptExportKey'' FALSE'? Если да, то какой код ошибки выполняет 'GetLastError'? – Vitaliy

+0

return FALSE && код ошибки f = 2148073485 – Vahagn

ответ

1

CryptExportKey имеет ограничение. Он требует для экспорта неглавных ключей в зашифрованном виде. Когда вы экспортируете пару открытых частей или RSA-ключей, это нормально, чтобы сделать второй параметр CryptExportKeyNULL и экспортировать ключ в незашифрованном виде. Однако вы не можете сделать то же самое для симметричного ключа, что должен указать ненулевой параметр hExpKey. Если указать hExpKey параметр, ваш код работает, смотрите пример:

#include <Windows.h> 
#include <cstdio> 

int main(int argc, char *argv[]) 
{ 
    // Create AES key 
    HCRYPTPROV hCryptProv_AES; 
    if (CryptAcquireContext(&hCryptProv_AES, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) 
    { 
     printf("A cryptographic provider has been acquired.\r\n"); 
    } 
    else 
    { 
     DWORD d = GetLastError(); 
     return -1; 
    } 
    HCRYPTKEY hSessionKey_AES; 
    if (!CryptGenKey(hCryptProv_AES, CALG_AES_256, CRYPT_EXPORTABLE, &hSessionKey_AES)) 
    { 
     DWORD d = GetLastError(); 
     return -1; 
    } 
    // Create RSA key to encrypt AES one 
    HCRYPTKEY hSessionKey; 
    if (!CryptGenKey(hCryptProv_AES, AT_KEYEXCHANGE, 1024 << 16, &hSessionKey)) 
    { 
     DWORD d = GetLastError(); 
     return -1; 
    } 
    // Export key 
    DWORD keylen; 
    BOOL ok = CryptExportKey(hSessionKey_AES, hSessionKey, SIMPLEBLOB, 0, NULL, &keylen); 
    if (ok == FALSE) 
    { 
     DWORD d = GetLastError(); 
     return -1; 
    } 
    BYTE *encKey = (BYTE *)malloc(keylen); 
    ok = CryptExportKey(hSessionKey_AES, hSessionKey, SIMPLEBLOB, 0, encKey, &keylen); 
    if (ok == FALSE) 
    { 
     DWORD d = GetLastError(); 
     return -1; 
    } 
    else 
     printf("A cryptographic key export succeeded.\r\n"); 
    return 0; 
} 

Если вы хотите сделать обмен ключами (позволяет сказать, что если вы хотите, чтобы Алиса отправить Бобу свой ключ AES), вы должны сделать следующее Этапы:

  1. Боб генерирует ключ RSA и отправляет свою публичную часть Алисе. Видишь, Боб начинает, а не Алиса!
  2. Боб посылает свою ключевую публичную часть Алисе.
  3. Алиса генерирует ключ AES.
  4. Алиса шифрует ключ AES с открытым ключом Боба.
  5. Алиса посылает ключ AES к Бобу.
  6. Боб использует свой секретный ключ для дешифрования ключа AES (то есть импортирует его с помощью CryptImportKey). Когда вы импортируете ключ, вы устанавливаете параметр hPubKey в значение, отличное от NULL, на самом деле вы устанавливаете его на ключевой дескриптор Боба, иначе импорт будет терпеть неудачу, поскольку ключ AES в зашифрованном виде.
+0

ok, но там, где я хочу импортировать, нужно использовать только int iii = CryptImportKey (hCryptProv_AES, (BYTE *) & exportKey_AES, keylen, NULL, NULL, & new_session_key); ? – Vahagn

+0

Я добавил объяснение, как обменять ключи на ответ. – Vitaliy

+0

хорошо, спасибо за обновление, я попробую исправить его :) спасибо !!! – Vahagn