使用WinAPI的简单AES加密 [英] Simple AES encryption using WinAPI

查看:722
本文介绍了使用WinAPI的简单AES加密的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在我的Qt / C ++应用程序中做简单的单块AES加密/解密。这是一个保持诚实的人的实现,所以只需要一个基本的加密(密钥,数据),我不用担心初始化向量等。我的输入和密钥将永远是16个字节。



我真的很希望避免与我的应用程序,所以我试图使用每个平台上可用的。在Mac上,这是一个单行的 CCCrypt 。在Windows上,我从$ code> WinCrypt.h 中的API中丢失。他们加密文件的例子大概是600线。



我正在查看 CryptEncrypt ,但我正在下降您必须创建的依赖关系的兔子洞才能调用。



任何人都可以提供使用Windows API进行AES加密的简单示例?当然有一种方法可以一两行。假设你已经有一个128位的密钥和128位的数据加密了。

解决方案

能够想出来欢迎提出改进意见!

  static void encrypt(const QByteArray& data,
const QByteArray&
QByteArray * encrypted){
//创建加密提供者上下文。
HCRYPTPROV hProvider = NULL;
if(!CryptAcquireContext(& hProvider,
NULL,// pszContainer = no named container
NULL,// pszProvider = default provider
PROV_RSA_AES,
CRYPT_VERIFYCONTEXT) ){
throw std :: runtime_error(无法创建加密提供程序上下文);
}

//构造密钥生成所需的blob。
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);

//创建Windows需要的加密密钥结构。
HCRYPTKEY hKey = NULL;
if(!CryptImportKey(hProvider,
reinterpret_cast< BYTE *>(& aes_blob),
sizeof(AesBlob128),
NULL,// hPubKey =未加密
0,// dwFlags
& hKey)){
throw std :: runtime_error(无法创建加密密钥);
}

// CryptEncrypt方法对输入和
//输出(!)使用*相同的*缓冲区,因此我们将要加密的数据复制到输出数组。
//此外,由于某些原因,Windows上的AES-128块密码需要两倍于
//输出缓冲区中的块大小。所以我们调整到这个长度,然后
//然后在完成之后切断多余的。
encrypted-> clear();
encrypted-> append(data);
encrypted-> resize(kAesBytes128 * 2);

//这样作为要编码的字节长度(在输入端)和
//生成的加密数据(在输出端)上使用的字节数。
DWORD length = kAesBytes128;
if(!CryptEncrypt(hKey,
NULL,// hHash = no hash
true,// Final
0,// dwFlags
reinterpret_cast< BYTE *> ;(加密 - > data()),
& length,
encrypted-> length())){
throw std :: runtime_error(Encryption failed
}

//查看上面的评论。
encrypted-> chop(length - kAesBytes128);

CryptDestroyKey(hKey);
CryptReleaseContext(hProvider,0);
}


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 encrypt(key, data) is necessary--I'm not worried about initialization vectors, etc. My input and key will always be exactly 16 bytes.

I'd really like to avoid another dependency to compile / link / ship with my application, so I'm trying to use what's available on each platform. On the Mac, this was a one-liner to CCCrypt. On Windows, I'm getting lost in the API from WinCrypt.h. Their example of encrypting a file is almost 600 lines long. Seriously?

I'm looking at CryptEncrypt, but I'm falling down the rabbit hole of dependencies you have to create before you can call that.

Can anyone provide a simple example of doing AES encryption using the Windows API? Surely there's a way to do this in a line or two. Assume you already have a 128-bit key and 128-bits of data to encrypt.

解决方案

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);
}

这篇关于使用WinAPI的简单AES加密的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆