这种加密方法是否安全?

时间:2014-04-26 19:47:48

标签: aes pbkdf2 c++

我使用Crypto ++在C ++中开发了一个应用程序来加密信息并将文件存储在硬盘中。我使用完整性字符串来检查用户输入的密码是否正确。如果实现生成安全文件,你能告诉我吗?我是密码学世界的新手,我用我读过的东西制作了这个程序。

string integrity = "ImGood"
string plaintext = integrity + string("some text");
byte password[pswd.length()]; // The password is filled somewhere else
byte salt[SALT_SIZE]; // SALT_SIZE is 32
byte key[CryptoPP::AES::MAX_KEYLENGTH];
byte iv[CryptoPP::AES::BLOCKSIZE];

CryptoPP::AutoSeededRandomPool rnd;
rnd.GenerateBlock(iv, CryptoPP::AES::BLOCKSIZE);
rnd.GenerateBlock(salt, SALT_SIZE);

CryptoPP::PKCS5_PBKDF2_HMAC<CryptoPP::SHA512> gen;
gen.DeriveKey(key, CryptoPP::AES::MAX_KEYLENGTH, 32,
              password, pswd.length(),
              salt, SALT_SIZE,
              256);

CryptoPP::StringSink* sink = new CryptoPP::StringSink(cipher);
CryptoPP::Base64Encoder* base64_enc = new CryptoPP::Base64Encoder(sink);
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption cfb_encryption(key, CryptoPP::AES::MAX_KEYLENGTH, iv);
CryptoPP::StreamTransformationFilter* aes_enc = new CryptoPP::StreamTransformationFilter(cfb_encryption, base64_enc);
CryptoPP::StringSource source(plaintext, true, aes_enc);

sstream out;
out << iv << salt << cipher;

然后将字符串流“out”中的信息写入文件。另一件事是我不知道派生函数中的“目的”参数是什么意思,我猜它是所需的密钥长度所以我把32,但我不确定,我找不到在Crypto ++手册中有关它的任何内容。

赞赏任何意见,建议或错误。

非常感谢你。

1 个答案:

答案 0 :(得分:5)

只有在您定义“安全”的含义时,文件才能“安全”。

通常,您会对两个属性感兴趣:

  • 机密性:加密的数据对攻击者来说仍然是不可读的;揭示明文数据需要了解特定的秘密。

  • 完整性:应可靠地检测到任何数据更改;攻击者不得以任何方式(即使是“盲目地”)修改数据,而不会对解密数据的人发现修改。

显然,您的代码在某种程度上履行了保密,但不履行诚信。您的名为“integrity”的字符串用词不当:是完整性检查。它的作用显然是检测意外密码错误,而不是攻击;因此,如果该字符串被称为passwordVerifier,则不会产生混淆。攻击者可以改变前48位以外的任何位,而解密过程不会注意到任何内容。

添加完整性(真品)需要使用MAC。安全地组合加密和MAC subject to subtleties;因此,建议使用加密和MAC authenticated encryption mode,它同时做到这两者,并且安全地做到这一点(即大群密码学家明确审查了这一特定组合)。通常推荐的AE模式包括GCMEAX

需要注意的一点是,在完整性很重要的环境中,数据在验证之前无法处理。这对大文件有影响:如果你的大文件装饰有单个MAC(无论是“手动”还是作为AE模式的一部分),那么在开始对明文数据做任何事情之前,你必须首先验证完整的文件。这对流式处理不起作用(例如,如果播放大型视频)。解决方法是将数据拆分为单独的块,每个块都有自己的MAC,但是必须注意块的排序(攻击者可能会尝试删除,复制或重新排序块):事情变得复杂。一般而言,复杂性对安全性不利。

在某些情况下,诚信无关紧要。例如,如果您的攻击模型是“攻击者窃取笔记本电脑”,那么您只需要关心机密性。但是,如果攻击模型是“攻击者窃取了笔记本电脑,修改了一些文件,并将其放回我的行李箱中而没有注意到”,那么完整性很重要:攻击者可以对文件进行修改,并推断出部分内容。在您下次访问文件时,根据您的外部行为保密。

为了保密,你使用CFB,这有点老式,但没有错。对于密码到密钥的转换,你使用PBKDF2,这很好;但是,迭代计数非常低:使用256.典型值为20000或更高。 theory是您应该使实际性能度量将此计数设置为您可以容忍的高值:值越高意味着处理速度越慢,无论是对于您还是对于攻击者而言,所以你应该提高它(取决于你的耐心)。


强制警告:您正在定义自己的加密,这是一条充满危险的路径。大多数人这样做会产生弱系统,其中包括训练有素的密码学家;事实上,作为一名训练有素的密码学家并不意味着您知道如何定义安全协议,而是您比定义自己的协议更清楚。因此,非常鼓励依赖现有协议(或格式),而不是自己制定协议。我建议OpenPGP,(例如)GnuPG作为支持库。即使您出于某种原因(例如许可证问题)需要重新实现格式,使用标准格式仍然是一个好主意:它避免引入弱点,它可以促进互操作性,并且可以针对现有系统进行测试。