在C++中解密AES加密字符串时出现冗余字符问题
AES解密后出现冗余字符的解决方法
我用C++的AES解密函数解密字符串时,得到了一些冗余字符。这套代码原本是为加密和解密原始字节编写的,以下是我的代码:
Python AES加密脚本
import sys from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Random import get_random_bytes import hashlib def encrypt_string(plaintext, key): iv = 16 * b'\x00' cipher = AES.new(hashlib.sha256(key).digest(), AES.MODE_CBC, iv) ciphertext = cipher.encrypt(pad(plaintext.encode(), AES.block_size)) return ciphertext KEY = get_random_bytes(16) try: plaintext = input(">> ") except: print("Input string needed!") sys.exit() ciphertext = encrypt_string(plaintext, KEY) print('AESkey[] = { 0x' + ', 0x'.join(hex(x)[2:] for x in KEY) + ' };') print('payload[] = { ' + ', '.join(str(x) for x in ciphertext) + ' };')
C++解密函数
int AESDecrypt(char * payload, unsigned int payload_len, char * key, size_t keylen) { HCRYPTPROV hProv; HCRYPTHASH hHash; HCRYPTKEY hKey; if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ return -1; } if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)){ return -1; } if (!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)){ return -1; } if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0,&hKey)){ return -1; } if (!CryptDecrypt(hKey, (HCRYPTHASH) NULL, 0, 0, payload, &payload_len)){ return -1; } CryptReleaseContext(hProv, 0); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return 0; }
问题原因
冗余字符来自PKCS#7填充:Python加密时用pad()函数给明文添加了填充字节,确保长度符合AES块大小(16字节)要求,但C++解密后没有移除这些填充内容。
解决方法
解密完成后,手动移除PKCS#7填充即可。PKCS#7的规则是:填充字节的数值等于填充的长度(比如缺3字节就填充3个0x03)。
修改后的C++解密函数如下:
// 定义AES块大小,避免硬编码 #define AES_BLOCK_SIZE 16 int AESDecrypt(char * payload, unsigned int payload_len, char * key, size_t keylen) { HCRYPTPROV hProv; HCRYPTHASH hHash; HCRYPTKEY hKey; if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ return -1; } if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)){ return -1; } if (!CryptHashData(hHash, (BYTE*)key, (DWORD)keylen, 0)){ return -1; } if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0,&hKey)){ return -1; } if (!CryptDecrypt(hKey, (HCRYPTHASH) NULL, 0, 0, (BYTE*)payload, &payload_len)){ return -1; } // 移除PKCS#7填充 if (payload_len == 0) return -1; unsigned char pad_len = payload[payload_len - 1]; // 验证填充合法性(可选但推荐,防止篡改或错误解密) if (pad_len > AES_BLOCK_SIZE || pad_len > payload_len) return -1; for (int i = payload_len - pad_len; i < payload_len; i++) { if (payload[i] != pad_len) return -1; } payload_len -= pad_len; // 给字符串添加结束符,确保C风格字符串正常使用 payload[payload_len] = '\0'; CryptReleaseContext(hProv, 0); CryptDestroyHash(hHash); CryptDestroyKey(hKey); return payload_len; // 返回实际明文长度,方便调用方处理 }
额外说明
- 建议将
payload参数改为BYTE*类型,避免字符类型的符号问题; - 填充验证步骤可以过滤非法的解密结果,提升安全性;
- 如果处理的是二进制数据而非字符串,可以省略添加
'\0'的步骤。
内容的提问来源于stack exchange,提问作者RockStar Techs
相关产品推荐
相关产品推荐

