大坑的aes GCM解密算法

C/C++代码 blackfeather

基于openssl库写的aes_gcm解密方法

兼容gcm 128、192、256位,兼容变长iv算法,与python和java的gcmdecrypt方法结果保持一致。

最恶心的地方在iv长度,要手动设置,否则某些情况下会与python或者java的结果不一致(代码的24行)。


std::string AesGCMDecrypt(const std::string &strKey, const std::string &strIV, const std::string &strBuffer, int nPadding/* = 1*/)
{
	std::string strRet;
	if (strBuffer.empty())
		return strRet;

	const EVP_CIPHER *cipher;
	if (strKey.length() == 16)
		cipher = EVP_aes_128_gcm();
	else if (strKey.length() == 24)
		cipher = EVP_aes_192_gcm();
	else if (strKey.length() == 32)
		cipher = EVP_aes_256_gcm();
	else
		return strRet;

	unsigned char *pszDecode = new unsigned char[strBuffer.length() + 32];
	ZeroMemory(pszDecode, strBuffer.length() + 32);
	unsigned char *pszOut = pszDecode;

	int nDecodeLen, nTotalLen = 0;
	EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
	EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL);
	if (strIV.length() != 12)
		EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, strIV.length(), NULL);
	EVP_DecryptInit_ex(ctx, NULL, NULL, (const unsigned char *)strKey.c_str(), (const unsigned char *)strIV.c_str());
	EVP_CIPHER_CTX_set_padding(ctx, nPadding);
	EVP_DecryptUpdate(ctx, pszOut, &nDecodeLen, (const unsigned char *)strBuffer.c_str(), strBuffer.length());
	nTotalLen = nDecodeLen;
	pszOut += nDecodeLen;

	EVP_DecryptFinal(ctx, pszOut, &nDecodeLen);
	nTotalLen += nDecodeLen;

	strRet.assign((const char *)pszDecode, nTotalLen);
	delete[] pszDecode;

	EVP_CIPHER_CTX_free(ctx);

	return strRet;
}



评论列表:

发表评论: