我正在使用 Crypto++ 来加密和解密文件,代码如下:
try {
EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(derived.data(), 32, ivb, ivb.size());
FileSource f(fileUrl.c_str(), false,
new AuthenticatedEncryptionFilter(encryptor, new FileSink(
std::string(fileUrl).c_str()), CryptoPP::AuthenticatedDecryptionFilter::THROW_EXCEPTION | CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_END ));
std::fstream file(fileUrl, std::ios::binary | std::ios::ate);
size_t remaining = file.tellg();
file.close();
size_t BLOCK_SIZE = 16384;
while (remaining && !f.SourceExhausted()) {
const unsigned int req = STDMIN(remaining, BLOCK_SIZE);
f.Pump(req);
f.Flush(false);
remaining -= req;
}
} catch (const CryptoPP::Exception& e) {
cout << e.GetWhat();
return 5;
}
解密:
try {
EAX<AES>::Decryption decryptor;
decryptor.SetKeyWithIV(derived2.data(), 32, ivb2, ivb2.size());
FileSource fe(fileUrl.c_str(), false,
new AuthenticatedDecryptionFilter(decryptor, new FileSink(
std::string(fileUrl).c_str()), CryptoPP::AuthenticatedDecryptionFilter::THROW_EXCEPTION | CryptoPP::AuthenticatedDecryptionFilter::MAC_AT_END ));
file.open(fileUrl, std::ios::binary | std::ios::ate);
size_t remaining = file.tellg();
remaining -= 3;
file.close();
size_t BLOCK_SIZE = 16384;
while (remaining && !fe.SourceExhausted()) {
const unsigned int req = STDMIN(remaining, BLOCK_SIZE);
fe.Pump(req);
fe.Flush(false);
remaining -= req;
}
} catch (const CryptoPP::Exception& e) {
cout << e.GetWhat();
return 5;
}
我的问题是,无论使用什么输入,该方法在解密时都不会抛出错误。我可以修改加密文件或使用其他密码或其他什么,我只会得到一个错误解密的文件,但也不异常(exception)。
据我所知,AuthenticatedDecryptionFilter
应该自动检查这些内容并抛出异常。
为什么没有抛出任何异常?
最佳答案
My Problem is, that this Method is not throwing an Error when decrypting no matter what inputs are used. I can modify the encrypted file or use another password or whatever, I only get an incorrectly decrypted file, but no exception...
Why is not throwing any exception?
缺点是, FileSource file(url.c_str(), false, new AuthenticatedDecryptionFilter...)
表示该消息不是 Put
因为 pumpAll=false
。因为消息不是Put
, LastPut
,触发MAC验证,没有被调用。您可以使用 MessageEnd
触发它,但你还没有读完消息,所以总是会失败。
我明白你想要做什么,而且解决方法比较棘手。
从大局来看,几乎一切都很好。在使用数据之前,您正在使用经过身份验证的加密和 MAC'ing。但我想知道单一或“一次”MAC 是否是解决该问题的方法。
要在这种情况下使用单个 MAC,您可能希望从验证中删除解密。您仍然想要执行这些操作,但是您希望将它们作为单独的步骤执行。在解密之前,您将验证整个消息的 MAC(只读操作,快速)。一旦MAC验证通过,就可以进行解密(读写操作,速度慢)。不幸的是,该库不提供单独的 EAX_Mac
您可以键入的类,使用消息,然后确定 MAC 是否良好。
也许可行的方法是在每个 block 大小的数据单元上应用 MAC,例如 4096 或 16384。这是 Bernstein 在 CAESAR Competition 中设想的用例或处理方式。 。竞赛的目的是下一代经过身份验证的加密方案。不幸的是,该库没有设置过滤器来执行此操作。
通过自定义过滤器将 MAC 应用到 block 大小的数据单元上是可能的,这在安全工程中是一个有趣的问题,因为每个安全上下文必须是唯一的。我认为解决这个问题的方法是......
创建 BlockedAuthenticatedEncryptionFilter
。而不是加密器对象的 key :
EAX<AES>::Encryption encryptor;
encryptor.SetKeyWithIV(derived.data(), derived.size(), iv, iv.size());
键入 BlockedAuthenticatedEncryptionFilter
相反:
FileSource f(... new BlockedAuthenticatedEncryptionFilter(
encryptor,
key.data(), key.size(),
iv, iv.size(),
new FileSink(...));
现在,BlockedAuthenticatedEncryptionFilter
将积累源数据。每当一个完整的 block 可用时,它就会在 key 和 iv 下对该 block 执行经过身份验证的加密。这是安全上下文下的加密 ( {message,key,iv}
),因此必须为下一个 block 或消息更改安全上下文。这就是为什么过滤器是关键的而不是模式的原因。
更改安全上下文 {message,key,iv}
对于下一条消息,您可以执行简单的 Increment
在 key 和 iv 上。这将确保每条消息的安全上下文都是唯一的。
您不能做的一件事就是调用encryptor.GetNextIV()
获得从密码状态导出的下一个确定性 iv。这是因为,根据设计,图书馆不提供它。这有时会出现在邮件列表中,但目前我找不到示例消息。
但是,不知道有什么麻烦next_key = Increment(key)
和next_iv = Increment(iv)
可能会导致,所以我需要考虑一下并进行一些研究。我可能会在 Security Stack Exchange 上询问。或Cryptography Stack Exchange ,也是。
关于c++ - 使用 AuthenticatedEncryptionFilter 时没有错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35464554/