我使用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;
}
我的问题是,无论使用什么输入,此方法在解密时都不会抛出错误。我可以修改加密文件或使用其他密码或其他任何密码,我只能获得错误解密的文件,但也不例外。
据我所知,AuthenticatedDecryptionFilter
应自动检查这些内容并抛出异常。
为什么不抛出任何异常?
答案 0 :(得分:2)
我的问题是,无论使用什么输入,此方法在解密时都不会抛出错误。我可以修改加密文件或使用其他密码或其他什么,我只得到一个错误解密的文件,但没有例外...
为什么不抛出任何异常?
缺点是, FileSource file(url.c_str(), false, new AuthenticatedDecryptionFilter...)
表示邮件 不 {{1因为 Put
。由于消息不是pumpAll=false
,因此不会调用触发MAC验证的 Put
。您可以使用 LastPut
触发它,但您不在信息的末尾,因此总是会失败。
我明白你要做的是什么,修复更棘手。
总体而言,几乎一切都还可以。在使用数据之前,您使用的是经过身份验证的加密和MAC。但是我想知道单身或者是一次拍摄&#34; MAC是解决问题的方法。
要在这种情况下使用单个MAC,您可能希望从验证中解除解密。您仍然希望这样做,但您希望将它们作为单独的步骤来执行。在解密之前,您将在整个消息上验证MAC(只读操作,快速)。 MAC验证后,然后执行解密(读写操作,慢速)。不幸的是,该库没有提供单独的 MessageEnd
类,您可以键入,使用该消息,然后确定MAC是否正常。
可能的方法是在每个块大小的数据单元上应用MAC,如4096或16384.这是Bernstein等人在CAESAR Competition中设想的用例或处理。该竞赛适用于下一代经过身份验证的加密方案。不幸的是,该库没有设置过滤器。
通过自定义过滤器在块大小的数据单元上应用MAC是可能的,并且它在安全工程中是一个有趣的问题,因为每个安全上下文必须是唯一的。我认为接近它的方法是......
创建EAX_Mac
。而不是键入加密器对象:
BlockedAuthenticatedEncryptionFilter
键入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(...));
将累积源数据。只要有完整块,它就会在密钥和iv下的块上执行经过身份验证的加密。这是安全上下文( BlockedAuthenticatedEncryptionFilter
)下的加密,因此必须针对下一个块或消息更改安全上下文。这就是为什么过滤器是键控的而不是模式。
要为下一封邮件更改安全上下文 {message,key,iv}
,您可以在密钥和密钥上执行简单的{message,key,iv}
IV。这将确保每条消息的安全上下文都是唯一的。
您 无法 做的一件事就是致电Increment
以获取从密码中获取的下一个确定性 iv #39; s州。这是因为,按照设计,图书馆不提供它。这有时会出现在邮件列表中,但我目前无法找到示例消息。
但是,我不确定encryptor.GetNextIV()
和next_key = Increment(key)
会导致什么问题,所以我需要考虑一下并对其进行一些研究。我可能会在Security Stack Exchange或Cryptography Stack Exchange上询问它。