Внедрение Windows CryptoAPI CryptDeriveKey с использованием API OpenSSL

У меня есть код CryptoAPI для шифрования\расшифровки данных с использованием AES-128 и ключа, полученного из пароля с использованием SHA-256.

Как я могу написать реализацию, эквивалентную OpenSSL, чтобы я мог шифровать данные с ее помощью, а затем расшифровывать их с помощью CryptoAPI и наоборот?

Попытка использовать EVP_BytesToKey с EVP_aes_128_cbc() и EVP_sha256() не работала «как есть». (Под «не работает» я имею в виду - не может расшифровать сгенерированные CryptoAPI зашифрованные данные и наоборот. Это работает для расшифровки зашифрованных данных OpenSSL).

Любая идея или хорошая ссылка?

Заранее спасибо.

Вот код Windows CryptoAPI:

// Get the handle to the default provider. 
      if(CryptAcquireContext(
                   &hCryptProv, 
                   NULL, 
                   MS_ENH_RSA_AES_PROV, 
                   PROV_RSA_AES, 
                   CRYPT_VERIFYCONTEXT))
          {
                   _tprintf(
                             TEXT("A cryptographic provider has been acquired. \n"));
          }
          else
          {
                   goto Exit_PrepareCAPI;
          }
          // Create a hash object. 
          if(!CryptCreateHash(
                   hCryptProv, 
                   HASH_ALGORITHM, 
                   0, 
                   0, 
                   &hHash))
          {
                   goto Exit_PrepareCAPI;
          }
          // Hash in the password data. 
          if(!CryptHashData(
                   hHash, 
                   (BYTE*) strPassword.c_str(),
                   strPassword.length(),
                   (DWORD)0)) 
          {
                   goto Exit_PrepareCAPI;
          }
          // Derive a session key from the hash object. 
          if(!CryptDeriveKey(
                   hCryptProv, 
                   ENCRYPT_ALGORITHM, 
                   hHash, 
                    0x00800000 /*128 bit*/, 
                   &hKey))
          { 
                   goto Exit_PrepareCAPI;
          }
          DWORD cryptMode = CRYPT_MODE_CBC;

          if(!CryptSetKeyParam(
                   hKey, 
                   KP_MODE, 
                   (BYTE*)&cryptMode, 
                   0))
          { 
                   goto Exit_PrepareCAPI;
          }

                   if(!CryptGetHashParam(
                   hHash,
                   HP_HASHSIZE,
                   (BYTE *)&dwHashLen,
                   &dwHashLenSize,
                   0))
          {
                   goto Exit_PrepareCAPI;
          }

          pbHash = new BYTE[dwHashLen];

          if(!CryptGetHashParam(
                   hHash,
                   HP_HASHVAL,
                   pbHash,
                   &dwHashLen,
                   0))
          {
                   goto Exit_PrepareCAPI;
          }

          SecureZeroMemory( ivBuff, sizeof(ivBuff) );

          for(DWORD i = 16, j = 0 ; i < dwHashLen ; i++, j++)
          {
                   ivBuff[j] = pbHash[i];
          }

          if(!CryptSetKeyParam(
                   hKey, 
                   KP_IV, 
                   ivBuff, 
                   0))
          { 
                   goto Exit_PrepareCAPI;
          }
          //
          // Read the data into pre-allocated pbBuffer
          //
// Encrypt data.           if(!CryptEncrypt(
                    hKey, 
                    NULL, 
                    fEOF,
                    0, 
                    pbBuffer, 
                    &dwCount, 
                    dwBufferLen))
{ 
                    goto Exit_MyEncryptFile;
          } 
Exit_MyEncryptFile:
          // Cleanup allocated objects

person rkellerm    schedule 25.01.2011    source источник


Ответы (1)


В конце концов, этот код работал:

int generateKey(const string& strSecter)
{    
SHA256_CTX sha256Ctx;
unsigned char hash[SHA256_DIGEST_LENGTH];
SecureZeroMemory(hash, sizeof hash);
SHA256_Init(&sha256Ctx);
SHA256_Update(&sha256Ctx, strSecter.c_str(), strSecter.length());
SHA256_Final(hash, &sha256Ctx);
memcpy(Key, hash, AES_BLOCK_SIZE);
memcpy(IV, hash + AES_BLOCK_SIZE, AES_BLOCK_SIZE);

return 0;
}

Надеюсь, это поможет кому-то.

person rkellerm    schedule 15.03.2011
comment
Насколько я понимаю, с результатом 32 байта SHA256 первые 16 байтов будут ключом, а оставшиеся 16 байтов будут IV. Как насчет SHA1 с 20 байтами? - person yelliver; 30.11.2016