Simple AES encryption using WinAPI

前端 未结 1 1860
你的背包
你的背包 2021-01-01 01:29

I need to do simple single-block AES encryption / decryption in my Qt / C++ application. This is a \"keep the honest people honest\" implementation, so just a basic en

相关标签:
1条回答
  • 2021-01-01 02:01

    Here's the best I've been able to come up with. Suggestions for improvement are welcome!

    static void encrypt(const QByteArray &data,
                        const QByteArray &key,
                        QByteArray *encrypted) {
      // Create the crypto provider context.
      HCRYPTPROV hProvider = NULL;
      if (!CryptAcquireContext(&hProvider,
                               NULL,  // pszContainer = no named container
                               NULL,  // pszProvider = default provider
                               PROV_RSA_AES,
                               CRYPT_VERIFYCONTEXT)) {
        throw std::runtime_error("Unable to create crypto provider context.");
      }
    
      // Construct the blob necessary for the key generation.
      AesBlob128 aes_blob;
      aes_blob.header.bType = PLAINTEXTKEYBLOB;
      aes_blob.header.bVersion = CUR_BLOB_VERSION;
      aes_blob.header.reserved = 0;
      aes_blob.header.aiKeyAlg = CALG_AES_128;
      aes_blob.key_length = kAesBytes128;
      memcpy(aes_blob.key_bytes, key.constData(), kAesBytes128);
    
      // Create the crypto key struct that Windows needs.
      HCRYPTKEY hKey = NULL;
      if (!CryptImportKey(hProvider,
                          reinterpret_cast<BYTE*>(&aes_blob),
                          sizeof(AesBlob128),
                          NULL,  // hPubKey = not encrypted
                          0,     // dwFlags
                          &hKey)) {
        throw std::runtime_error("Unable to create crypto key.");
      }
    
      // The CryptEncrypt method uses the *same* buffer for both the input and
      // output (!), so we copy the data to be encrypted into the output array.
      // Also, for some reason, the AES-128 block cipher on Windows requires twice
      // the block size in the output buffer. So we resize it to that length and
      // then chop off the excess after we are done.
      encrypted->clear();
      encrypted->append(data);
      encrypted->resize(kAesBytes128 * 2);
    
      // 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);
    
      CryptDestroyKey(hKey);
      CryptReleaseContext(hProvider, 0);
    }
    
    0 讨论(0)
提交回复
热议问题