我有一些代码用于加密和解密 ios 应用程序中的一些字符串。该代码涉及使用 CCCrypt。是否有可靠的方法来测试所使用的密钥的有效性,而无需将密钥实际存储在任何地方?根据我的研究,似乎接近判断密钥是否有效的唯一方法是使用密钥长度和密钥哈希。任何人都可以指导我正确的方向吗?
3 回答
获得答案需要一些关于正确加密的背景知识。您可能已经知道这一点,但大多数人都做错了,所以我将覆盖它。(如果您使用密码进行加密并且没有对至少一个 HMAC、两个盐和一个 IV 进行编码,那么您做错了。)
CCHmac()
首先,您必须在任何时候使用未经身份验证的模式(例如 AES-CBC)进行加密时使用 HMAC(请参阅参考资料)。否则,攻击者可以修改您的密文,使其解密为不同的消息。有关此攻击的示例,请参见模式。HMAC 是基于密钥的加密安全哈希。
其次,如果您使用基于密码的加密,则必须使用 KDF 将其转换为密钥。最常见的是 PBKDF2。您不能只将密码字节复制到密钥中。
假设您以这种方式使用密码,您通常会生成两个密钥,一个用于加密,一个用于 HMAC。
好的,有了这些部分,您可以验证密码是否正确,因为如果不正确,HMAC 将失败。这就是RNCryptor的做法。
这种简单的方法有两个问题:您必须在验证密码之前处理整个文件,并且无法检测文件损坏与密码错误。
为了稍微解决这些问题,您可以添加一小块单独的 HMAC 额外数据。然后,您验证那个小块而不是整个文件。这基本上就是aescrypt的做法。具体来说,他们生成一个“真实”密钥来加密整个文件,然后使用 PBKDF2 生成的密钥和 HMAC 分别加密该密钥。某些形式的损坏仍然看起来像错误的密码,但通过这种方式将它们区分开来更容易一些。
您可以将使用密钥加密的已知值存储在数据库中。验证密钥是否正确很简单:加密已知字符串,并将其与数据库中的加密输出进行比较。如果您坚持使用单个数据块,那么您不必担心操作模式并且可以保持简单。
也可以存储密钥的哈希值,但我会将密钥视为密码,并采取在数据库中存储密码时所采取的所有防御措施(例如,使用 bcrypt、对哈希值加盐等)。
如果您无法存储这些值,您可以在不知道实际内容但可能知道消息的某些属性(例如 ASCII 文本、字符串中某处有今天的日期等)的情况下解密某些内容并测试解密的内容这些属性的消息。然后,如果解密后的块不具有这些属性(例如,设置了 MSB 的字节,没有日期实例),您就知道密钥无效。在这种情况下存在误报的可能性,但几率非常低。
一般来说,我同意彼得·埃利奥特的观点。但是,我还有一些额外的评论:
a) 如果密钥是随机生成的,那么存储密钥的哈希值是安全的
b)您始终可以将原始消息的哈希附加到加密消息(如果您可以控制的话)。在这种情况下,您可以解密消息,获取解密消息的哈希并将其与原始消息的哈希进行比较。如果它们是 eqaul,则使用正确的密钥进行解密。