我使用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手册中的任何内容.
任何意见,建议或错误指出表示赞赏.
非常感谢你提前.
解决方法:
只有在您定义“安全”的含义时,文件才能“安全”.
通常,您会对两个属性感兴趣:
>机密性:加密的数据对于攻击者来说仍然是不可读的;揭示明文数据需要了解特定的秘密.
>完整性:应可靠地检测数据的任何变更;攻击者不得以任何方式(甚至“盲目地”)修改数据,而不会解密数据的人注意到修改.
显然,您的代码片段在某种程度上实现了机密性,但不实现完整性.您的字符串称为“完整性”用词不当:它不是完整性检查.它的作用显然是发现意外的密码错误,而不是攻击;因此,如果该字符串被称为passwordVerifier,则会更容易混淆.攻击者可以在前48位之外改变任何位,而解密过程不会注意到任何事情.
添加完整性(真品)需要使用MAC.安全地结合加密和MAC是subject to subtleties;因此,建议使用加密和MAC authenticated encryption mode同时进行加密,并且安全地进行加密(即特定组合由成群的密码学家明确审查).通常推荐的AE模式包括GCM和EAX.
需要注意的一点是,在完整性很重要的环境中,数据在验证之前无法处理.这对大文件有影响:如果你的大文件装饰有单个MAC(无论是“手动”还是作为AE模式的一部分),那么在开始对明文数据做任何事情之前,你必须首先验证完整的文件.这对流式处理不起作用(例如,如果播放大型视频).解决方法是将数据拆分为单独的块,每个块都有自己的MAC,但是必须注意块的排序(攻击者可能会尝试删除,复制或重新排序块):事情变得复杂.一般而言,复杂性对安全性不利.
在某些情况下,诚信无关紧要.例如,如果您的攻击模型是“攻击者窃取笔记本电脑”,那么您只需要关心机密性.但是,如果攻击模型是“攻击者窃取了笔记本电脑,修改了一些文件,并将其放回我的行李箱中而没有注意到”,那么完整性很重要:攻击者可以对文件进行修改,并推断出部分内容.在您下次访问文件时,根据您的外部行为保密.
为了保密,你使用CFB,这有点旧式,但没有错.对于密码到密钥的转换,你使用PBKDF2,这很好;但是,迭代计数非常低:使用256.典型值为20000或更高. theory是你应该做出实际的性能测量,把这个数量设置为你可以忍受的高值:更高的值意味着你和攻击者的处理速度都会变慢,所以你应该把它调高(取决于你的忍耐).
强制警告:您正在定义自己的加密,这是一条充满危险的路径.大多数人这样做会产生弱系统,其中包括训练有素的密码学家;事实上,作为一名训练有素的密码学家并不意味着您知道如何定义安全协议,而是您比定义自己的协议更清楚.因此,我们非常鼓励您依赖现有的协议(或格式),而不是自己制作协议.我建议OpenPGP,(例如)GnuPG作为支持库.即使您出于某种原因(例如许可证问题)需要重新实现格式,使用标准格式仍然是一个好主意:它避免引入弱点,它提升了互操作性,并且可以针对现有系统进行测试.