基于openssl库写的aes_gcm解密方法
兼容gcm 128、192、256位,兼容变长iv算法,与python和java的gcmdecrypt方法结果保持一致。
最恶心的地方在iv长度,要手动设置,否则某些情况下会与python或者java的结果不一致(代码的24行)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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; } |
中间还尝试了EVP_aead_aes_256_gcm()方法,同样无效。
还好最后找到博主的这篇笔记,感谢!