C++客户端加密文件传Python服务器解密后丢失前16字节的解决方法
问题:AES加密传输后丢失前16字节的解决方法
用C++ Crypto++编写的客户端加密文件后,发送给Python Crypto.Cipher实现的服务器,解密后原文件前16个字符总是丢失。例如原文件内容为AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC,解密后变为BBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCC。
相关代码
C++客户端加密函数
std::string encryptFile(const std::string& filename, const CryptoPP::SecByteBlock& key) { // Step 1: Read the file to be encrypted std::ifstream input_file(filename, std::ios::binary); std::string plaintext((std::istreambuf_iterator<char>(input_file)), std::istreambuf_iterator<char>()); CryptoPP::SecByteBlock iv(CryptoPP::AES::BLOCKSIZE); CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor(key, key.size(), iv); // Step 2: Encrypt the file std::string ciphertext; CryptoPP::StringSource s(plaintext, true, new CryptoPP::StreamTransformationFilter(encryptor, new CryptoPP::StringSink(ciphertext))); return ciphertext; }
Python服务器解密函数
def decrypt_file(self, encrypted_data, aes_key, file_path): key = base64.b64decode(aes_key) iv = encrypted_data[:AES.block_size] cipher = AES.new(key, AES.MODE_CBC, iv=iv) plaintext = cipher.decrypt(encrypted_data[AES.block_size:]) # Remove PKCS#7 padding padding_len = plaintext[-1] plaintext = plaintext[:-padding_len] with open(file_path, "wb") as f: f.write(plaintext)
解决方法
问题核心是客户端未将IV(初始化向量)写入加密后的密文头部,但服务器默认从加密数据的前16字节读取IV,相当于把密文的前16字节误当成了IV,剩下的密文解密自然缺失了前16字节内容。同时原客户端代码的IV是未初始化的垃圾值,存在安全隐患,必须修正。
1. 修改C++客户端加密逻辑
生成随机合法的IV,并将其拼接在密文的最前方再发送:
std::string encryptFile(const std::string& filename, const CryptoPP::SecByteBlock& key) { // 读取文件内容 std::ifstream input_file(filename, std::ios::binary); std::string plaintext((std::istreambuf_iterator<char>(input_file)), std::istreambuf_iterator<char>()); // 生成随机IV(AES-CBC要求IV必须随机且唯一,禁止使用未初始化值) CryptoPP::SecByteBlock iv(CryptoPP::AES::BLOCKSIZE); CryptoPP::AutoSeededRandomPool prng; prng.GenerateBlock(iv, iv.size()); CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor(key, key.size(), iv); std::string ciphertext; // 先将IV写入密文开头 ciphertext.assign(reinterpret_cast<const char*>(iv.data()), iv.size()); // 执行加密并追加到密文后 CryptoPP::StringSource s(plaintext, true, new CryptoPP::StreamTransformationFilter(encryptor, new CryptoPP::StringSink(ciphertext))); return ciphertext; }
2. 服务器端无需修改
当前Python服务器的逻辑是正确的:从加密数据头部读取IV,用剩余内容解密,只要客户端补上IV,就能正常解密出完整的原文件。
内容的提问来源于stack exchange,提问作者mudcip
相关产品推荐
相关产品推荐

