如果密码无效,使AES解密失败

5
我最近在使用PyCrypto编写项目时,使用AES编写了自己的加密方法。我使用哈希生成32字节的密码,并将其提供给使用CBC的AES-256位加密。文件输入使用PKCS#7填充进行填充,以符合可被16整除的要求。
我可以正常加密和解密文件,并且最初加密的输入文件与输出文件具有相同的SHA-256哈希值。
唯一的问题是,如果我提供了错误的口令,解密仍会发生。对于我的工作来说,这是一个问题,因为如果口令不正确,我需要让解密快速失败。
如何实现这个功能?我听说过其他AES加密方法,但似乎PyCrypto仅支持ECB、CBC、CFB、OFB、CTR和OpenPGP。我该如何实现加密强度更高的AES,使得没有正确的口令就无法解密?

1
我已经编写了自己的加密方法 -- 这就是你的问题所在。 - user395760
1
我没有编写自己的加密方法。我编写了一个使用AES作为加密方法的程序。我并不是那么蠢。 - Naftuli Kay
AES只是一种原语(块密码)。我明白你所说的“加密方法”指的是使用这种原语(以及其他原语)实现更高级别目的(基于密码的任意数据加密)。这就是我的意思:这仍然是你自己不应该做的事情。 - user395760
你能推荐一个安全的加密方法吗?它需要提供256位的加密,使用强大且缓慢的哈希方法作为密钥,并且可以在不知道文件的完整长度的情况下进行加密。如果有一个符合我所有要求的即插即用解决方案,那将是太棒了。 - Naftuli Kay
我相信已经有现成的解决方案,但我不是专家。至少对于哈希部分,有PBKDF2。将流密码应用于任意长度的明文也是由专家编写和审查的软件定期完成的(另一方面,加密人员每隔一个月就会提出更复杂的攻击)。至于将两者结合起来,我感到困惑,但我认为已经存在标准,尽管可能没有开源实现。 - user395760
我正在使用的哈希方法是bcrypt,但可以很容易地被PBKDF2替换。结合AES-256位加密,这似乎表明具有高安全性。当然,在进行任何重要操作之前,我可能会雇用密码学家来分析我的方法。 - Naftuli Kay
3个回答

5
确保您的密文在更改后无法解密的最佳方法是添加身份验证标记。身份验证标记用于提供密文的身份验证和完整性。
此标记可以由MAC(例如使用SHA-256的AES-CMAC或HMAC)组成,以覆盖密文。但是这需要第二个密钥才能确保安全。
另一种方法是使用经过身份验证的加密(如GCM)。 GCM使用单个密钥并生成身份验证标记(大小可以配置)。
确保使用正确生成的IV。 IV可以添加到密文前缀,并且在计算身份验证标记时包含它,并且不要忘记您的纯文本大小可能不会隐藏。
在解密密文之前,应该先验证标记的正确性。 请注意通常情况下,您不应加密密码,除非您需要在以后精确访问密码。对于密码验证,请改用PBKDF2。

我目前正在使用哈希方法来处理密码,具体来说是bcrypt,不过我可能会使用PBKDF2。不幸的是,在Python中几乎没有对认证AES模式的支持。我对加密文本进行MAC处理的知识几乎为零,有什么建议可以指导我开始学习吗?我想使用一些自动化工具来完成这个过程,以便我能够减少出错的机会并提高安全性。 - Naftuli Kay
这篇文章似乎做了很多正确的事情。使用HMAC和SHA256,两个密钥,在HMAC中使用IV。不能完全保证其可靠性,但它看起来肯定没问题... - Maarten Bodewes

3

关于AES(或其他任何加密算法),没有任何东西能让您知道您是否有正确的密钥。不过,当您想在数学之外使用密码学时,这是一个非常有用的功能。

您需要做的是在消息开头添加一个已知值的块,这样在解密第一个块后,您可以将其与已知值进行比较,并知道您是否有了错误的密钥。如果要加密的数据具有已知标头,则可以使用此方法。

另外,您可以发送密钥的加密哈希(例如SHA-256)以及消息,只有在攻击者能够破解哈希时才能恢复密钥。


1
我不是加密专家,但如果明文的第一个块是已知值,攻击者是否可以轻松地从密文的第一个块(和IV,如果适用的话,但这包含在明文中)中获取密钥? - user395760
我希望不是这样,因为那将是一种已知明文攻击。如果你非常谨慎,可以将第一个块作为密钥,或者密钥的某个不可逆哈希值。 - jleahy
1
@JeffreyHantin 如果密钥具有足够的熵,例如如果它是随机生成的,则这不是问题。请注意,这是关于加密密码,而不是使用密码加密某些内容。 - Maarten Bodewes
1
警告:接受的答案使用了非标准的加密实践。在密文上进行MAC或进行认证加密是接受或拒绝密文的方式。 - Maarten Bodewes
2
@JeffreyHantin 这个问题已经被同时发布到crypto,没有太多提示,讨论在那里继续。 - Maarten Bodewes
显示剩余6条评论

0
为了提供所需的快速失败属性,您需要在被加密的数据前面添加一个标题。我建议使用一个随机的“混淆器”nonce(类似于密码salt),并与已知常量“magic number”连接起来;混淆器的存在将像盐一样,提供一定程度的防御,以抵御基于预计算表的攻击。
有了这样的标题,您只需要解密标题并验证魔术数字字段;如果它不匹配已知常量,则密钥无效。如果匹配,则丢弃标题并处理输入的其余部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接