aes - 这种加密方法安全吗?

标签 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”中的信息写入文件。另一件事是我不知道派生函数中的“目的”参数是什么意思,我猜它是所需的 key 长度,所以我放了 32,但我不确定,我找不到Crypto++ 手册中有关它的任何内容。

任何意见,建议或指出的错误表示赞赏。

非常感谢您提前。

最佳答案

仅当您定义“安全”的含义时,文件才可以是“安全的”。
通常,您会对两个属性感兴趣:

  • 保密 : 加密的数据对攻击者来说是不可读的;揭示明文数据需要了解特定的 secret 。
  • 诚信 :应可靠地检测到数据的任何更改;攻击者不得以任何方式(甚至“盲目地”)修改数据,而解密数据的任何人都不会注意到修改。

  • 显然,您的一段代码实现了 secret 性(在某种程度上),但不符合完整性。您名为“integrity”的字符串用词不当:它不是完整性检查。它的作用显然是检测意外的密码错误,而不是攻击;因此,如果该字符串被称为 passwordVerifier 就不那么令人困惑了。反而。攻击者可以更改前 48 位以外的任何位,而解密过程不会注意到任何内容。
    添加完整性(真正的东西)需要使用 MAC .安全地结合加密和 MAC 是 subject to subtleties ;因此,建议使用加密和MAC an authenticated encryption mode两者都可以,并且安全地进行(即特定组合已由成群的密码学家明确审查)。通常推荐的AE模式包括GCMEAX .
    需要注意的重要一点是,在完整性很重要的上下文中,数据在经过验证之前无法进行处理。这对大文件有影响:如果您的大文件装饰有单个 MAC(无论是“手动”还是作为 AE 模式的一部分),那么您必须先验证完整文件,然后再开始对纯文本数据执行任何操作。这不适用于流式处理(例如,如果播放大型视频)。一种解决方法是将数据拆分为单独的 block ,每个 block 都有自己的 MAC,但是必须注意 block 的排序(攻击者可能会尝试删除、复制或重新排序 block ):事情变得复杂。一般来说,复杂性不利于安全。
    在某些情况下,完整性无关紧要。例如,如果您的攻击模型是“攻击者窃取笔记本电脑”,那么您只需关心 secret 性。然而,如果攻击模型是“攻击者偷了笔记本电脑,修改了一些文件,然后在我没有注意到的情况下把它放回了我的手提箱”,那么完整性很重要:攻击者可以在文件中进行修改,并推断出部分当您下次访问文件时,根据您的外部行为对自身进行保密。
    为保密起见,您使用 CFB ,这有点老式,但没有错。对于密码到 key 的转换,您使用 PBKDF2,这很好;但是,迭代次数非常少:您使用 256。典型值是 20000 或更多。 theory是您应该采取实际的性能措施来将此计数设置为您可以容忍的尽可能高的值:较高的值意味着处理速度较慢,无论是对您还是对攻击者而言,因此您应该提高它(取决于您的耐心) .

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

    关于aes - 这种加密方法安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23349266/

    相关文章:

    java - PBKDF2WithHmacSHA512 对比。 PBKDF2WithHmacSHA1

    java - BCrypt 与 PBKDF2WithHmacSHA1

    UIImage 上的 Iphone 加密 - AES 256 加密时出现 kCCBufferTooSmall 错误

    encryption - AES 输出 block 大小

    python - CCKeyDerivationPBKDF 线程安全吗?

    java - 将 jdouble* native 变量解析为 double* native 变量 (jni)

    c++ - 函数声明中的等式

    c++ - AES 解密大于可用 RAM 的文件

    c++ - AES/CBC 加密和解密之间的速度差异?

    java - java和C++之间的字符串大小关系