当我尝试使用 python Crypto.Cipher aes 和 php openssl 解密一些数据(在 C++ 中使用 openssl 加密 - 下面的代码)时,出现了相同的错误 - 字符串的开头被替换为随机二进制字符,如下所示:
{"pass":"azertyu","opt":...
替换为:
"Ž{mÂ┬X▒ Íł.Q>4","opt":...
这可能是填充问题,但我无法弄清楚。
要解密的Python代码:
def decrypt(ciphertext_hex):
key = b"t*H3_B3$t/k$%evr"
data = binascii.unhexlify(ciphertext_hex)
iv = data[:AES.block_size]
data = data[AES.block_size:]
cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(data), AES.block_size)
print(decrypted)
# return decrypted.decode("utf-8", errors="replace")
return decrypted.decode("utf-8")
要加密的C++代码:
std::string binToHex(const std::string &input)
{
std::ostringstream hexStream;
hexStream << std::hex << std::setfill('0');
for (unsigned char c : input)
{
hexStream << std::setw(2) << static_cast<int>(c);
}
return hexStream.str();
}
std::string crypt(const std::string &data, const std::string &key)
{
const unsigned char *keyBytes = reinterpret_cast<const unsigned char *>(key.c_str());
const unsigned char *dataBytes = reinterpret_cast<const unsigned char *>(data.c_str());
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
AES_KEY aesKey;
if (AES_set_encrypt_key(keyBytes, 128, &aesKey) < 0) {
std::cout << "key";
return "";
}
unsigned char iv[AES_BLOCK_SIZE];
if (RAND_bytes(iv, AES_BLOCK_SIZE) != 1)
{
std::cout << "rand bytes";
return "";
}
size_t paddedLen = (data.length() + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE * AES_BLOCK_SIZE;
unsigned char *paddedData = new unsigned char[paddedLen];
std::memcpy(paddedData, dataBytes, data.length());
memset(paddedData + data.length(), paddedLen - data.length(), paddedLen - data.length());
unsigned char ciphertext[paddedLen];
AES_cbc_encrypt(paddedData, ciphertext, paddedLen, &aesKey, iv, AES_ENCRYPT);
std::string output(reinterpret_cast<char *>(iv), AES_BLOCK_SIZE);
output.append(reinterpret_cast<char *>(ciphertext), paddedLen);
delete[] paddedData;
return binToHex(output);
}
如评论中所示,IV 发生了变化。数据只是被最后一个块的密文替换,这是在对下一个块进行块加密之前改变明文的向量。请参阅 CBC 上的维基百科页面了解更多信息。
现在您可能会问为什么要更改 IV,因为这并不能保护用户免受您遇到的问题的影响。但是,请记住,如果您使用AES_
功能,您使用的是 AES 的低级软件实现。如文档中这些函数为 AES 对称提供了低级接口 密码算法,也称为 Rijndael。出于灵活性的考虑, 建议应用程序使用所描述的高级接口 在
EVP_EncryptInit(3)除非和 EVP_aes_128_cbc(3) 只要有可能就可以。
所以我根本不认为 C++ 可以接受;应避免使用这些低级函数
有非常具体的使用它们的要求。