为 PHP 加密创建 HMAC

Creating HMAC for PHP encryption

我一直在考虑将 HMAC 添加到 PHP mcrypt 加密。

这只是使用加密密钥通过 hash_hmac 对加密数据进行哈希处理并将其附加到加密数据吗?然后在解密时分离 HMAC,hash_hmac 其余数据再次使用密钥并检查它是否与 HMAC 匹配。

我很困惑,因为在这个 SO 问题中 When authenticating ciphertexts, what should be HMACed? 它说:

you have to include in the HMAC input everything that impacts the decryption process, i.e. not only the encryption result per se, but also the IV which was used for that encryption, and, if the overall protocol supports algorithm agility, you should also input the specification of the encryption algorithm (otherwise, an attacker could alter the header of your message to replace the tag which says "AES-256" with the tag which says "AES-128" and you would unknowingly decrypt with the wrong algorithm).

是这样吗?如果这是真的,为什么仅对加密数据使用 hash_hmac 还不够?

简答:是

长答案:

HMAC是基于Hash的消息认证码。你应该 HMAC 任何你想验证的东西,或者换句话说,任何你想防止被修改的东西。

虽然 the RFC standard 更复杂,但将 HMAC 视为加盐哈希可能有意义。

e.g. hmac(message, key) = hash(message + key)

  1. 您只能使用相同的消息和密钥重新创建相同的 hmac。
  2. 如果密钥相同但消息不同,您不能重新创建相同的 hmac。
  3. 如果消息相同但密钥不同,您不能重新创建相同的 hmac。

攻击者(没有 HMAC 密钥)无法在不使现有 HMAC 无效的情况下修改部分 HMAC 消息。它确实取决于您的数据格式和您对该数据的使用来确定应包含在 HMAC 消息和 HMAC 密钥中的内容。但是假设您使用 HMAC 来验证解密,那么 您应该始终在 HMAC 消息中包含解密所依赖的任何内容。对称密钥通常用作 HMAC 密钥。

在你的引述中,张贴者说 IV 和算法也应该被散列。考虑由

组成的 file/database 格式

ALGORITHM + IV + CIPHERTEXT + HMAC

如果您只对密文进行 HMAC,攻击者将能够修改算法或 IV(破坏文件)而不影响 HMAC 的有效性。这很糟糕,因为您最终可能会得到一个带有有效 HMAC 的损坏的加密文件。解密将照常进行,因为您的软件会认为一切正常。结果是完全乱码的解密,但关键是你的软件坏了,因为它在解密时返回了错误的输出并且没有给出任何错误。这可以归类为 'security risk' 如果您的应用程序试图对错误数据执行某些操作,因为它假定它是正确的。它 不是 安全风险,因为它会使底层加密变得更弱或更容易破解。 HMAC 和对称加密是两种完全不同的技术,做不同的事情。使用 HMAC 的要点是您可以假设解密层返回的数据是 100% 正确的。

在上面的例子中,ALGORITHM 是一个动态数据,我在 OP 引用中用来解释“算法敏捷性”。它定义了使用的加密算法。关键是它是 dynamic 所以它需要从某个地方读取而不是硬编码。这一事实使它成为解密的依赖项,因此它应该包含在 HMAC 消息 中。但是,如果您总是使用某些 static 算法,那么它应该由您的解密代码假定(硬编码到)并且无论如何都不需要存储此数据。不需要在HMAC消息中包含静态数据,因为它对解密没有影响。

使用静态算法的文件格式的一个例子是the open source AES-256 Crypt File Format。该算法是一致的,因此它始终是假定的。出于速度原因,它实际上使用了 2 个 HMAC。 1 验证 IV 和密钥,2nd 验证加密数据部分。