我为一段文本编写了一个简单的AES加密程序,每当我尝试解密该文本时,都会抛出错误;
StreamTransformationFilter:密文长度不是块大小的倍数
这是我的加密方法;
comment
cryptkey结构;
c_crypto::cryptkey aes_key;
c_crypto::make_keys(aes_key);
std::string testmessage = "test";
c_crypto::encrypt_buffer(testmessage, aes_key.enc_key, aes_key.enc_iv);
c_crypto::decrypt_buffer(testmessage, aes_key.enc_key, aes_key.enc_iv);
std::cout << testmessage << std::endl;
struct cryptkey {
unsigned char enc_key[AES_KEY_SIZE];
unsigned char enc_iv[AES_KEY_SIZE];
};
= 16
AES_KEY_SIZE
函数只是调用;
make_keys()
使用void c_crypto::random_bytes(const int &amount, unsigned char *result) {
CryptoPP::AutoSeededRandomPool rng;
rng.GenerateBlock(result, amount);
}
或AES_KEY_SIZE
的{{1}}的参数
在解密功能中
cryptkey.enc_iv
在stfDecryptor.MessageEnd()中引发错误;
如果有任何用途,这里是加密功能;
cryptkey.enc_key
编辑:
这是我的解码和编码功能:
void c_crypto::decrypt_buffer(std::string &input, unsigned char key[AES_KEY_SIZE], unsigned char iv[AES_KEY_SIZE]) {
input = base64_decode(input);
CryptoPP::AES::Decryption aesDecryption(key, AES_KEY_SIZE);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(input));
stfDecryptor.Put(reinterpret_cast<const unsigned char*>(input.c_str()), input.size());
stfDecryptor.MessageEnd();
}
答案 0 :(得分:1)
void c_crypto::encrypt_buffer(std::string &input, unsigned char key[AES_KEY_SIZE], unsigned char iv[AES_KEY_SIZE]) { CryptoPP::AES::Encryption aesEncryption(key, AES_KEY_SIZE); CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv); CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(input)); stfEncryptor.Put(reinterpret_cast<const unsigned char*>(input.c_str()), input.length()); stfEncryptor.MessageEnd(); input = base64_encode(input); }
不要像您一样使用相同的字符串作为源和接收器。改用单独的临时文件。
大多数(全部?)块密码可以采用16字节的块,并就地加密或解密。但是,对于字符串,as字符串会更改基础分配更改。当分配更改时,基础指针也会更改。
也许使用类似以下的内容。临时人员回避了使用字符串作为源和接收器的问题。它还提供了更好的异常安全性。如果有东西横盘整理,您的input
将保持不变。
void c_crypto::encrypt_buffer(std::string &input, unsigned char key[AES_KEY_SIZE], unsigned char iv[AES_KEY_SIZE]) {
AES::Encryption aesEncryption(key, AES_KEY_SIZE);
CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);
std::string encrypted; encrypted.reserve(input.size()+16);
StreamTransformationFilter stfEncryptor(cbcEncryption, new StringSink(encrypted));
stfEncryptor.Put(reinterpret_cast<const unsigned char*>(input.c_str()), input.length());
stfEncryptor.MessageEnd();
std::string encoded = base64_encode(encrypted);
std::swap(encoded, input);
}
void c_crypto::decrypt_buffer(std::string &input, unsigned char key[AES_KEY_SIZE], unsigned char iv[AES_KEY_SIZE]) {
std::string decoded = base64_decode(input);
std::string decrypted; decrypted.reserve(decoded.size());
AES::Decryption aesDecryption(key, AES_KEY_SIZE);
CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);
StreamTransformationFilter stfDecryptor(cbcDecryption, new StringSink(decrypted));
stfDecryptor.Put(reinterpret_cast<const unsigned char*>(decoded.c_str()), decoded.size());
stfDecryptor.MessageEnd();
std::swap(decrypted, input);
}
使用缓冲区作为输入/输出参数可以正常工作。在此示例中,指针在整个过程中不会改变:
byte buff[16] = {0};
CBC_Mode<AES>::Encryption enc(key, 16, iv);
enc.ProcessBlock(buff);
但是,您的用例有些棘手,因为密文通过input
附加到字符串StringSink(input)
上,这不可避免地使input
增长并使通过StringSource(input, ...)
将数据馈送到加密器的迭代器无效。
如果有兴趣,ProcessBlock
和ProcessString
是用于转换数据的低级成员函数。像StreamTransformationFilter
这样的过滤器只会为您调用它。没有魔术或恶作剧。这只是一种处理数据的高级方法。另请参阅《 doxygen手册》中的BlockTransformation
。
关于填充,您使用了:
StreamTransformationFilter stfEncryptor(cbcEncryption, new StringSink(input));
实际上是哪个StreamTransformationFilter
构造函数:
StreamTransformationFilter (StreamTransformation &c, BufferedTransformation *attachment=NULL, BlockPaddingScheme padding=DEFAULT_PADDING)
DEFAULT_PADDING
是两件事之一。对于需要填充的模式,例如ECB和CBC,它是PKCS#7填充(PKCS_PADDING
)。对于不需要需要填充的模式,例如CTR,则无需填充(NO_PADDING
)。
在填充方案方面,通常应该使用默认设置。