PHP 带校验和的双向加密

PHP Two Way Encryption With Checksum

我正在尝试使用 URL 参数(对于内部 SSO 服务器)将 JSON 字符串从一个 Web 应用程序传递到另一个 Web 应用程序。

我需要做的是能够使用预共享密钥加密 JSON 字符串(这是一个用户有效载荷对象),将用户转发到附加有效载荷的服务提供商应用程序URL 参数,然后在服务提供商应用程序上将有效负载解密回 JSON 字符串以获取所需信息。

由于 PHP 的所有内置加密功能,现在这部分不是什么大问题,但下一部分是困难。我需要在加密字符串中嵌入一个校验和,可以在解密时检查它,这样如果它在传输过程中被修改,我就可以引发异常。

这样做的目的是确保用户负载在传输过程中没有被意外或故意修改。

您要提供的不止一个"checksum"(通常定义为"calculable by any party");您要提供身份验证标签或消息身份验证代码 (MAC)。您有几个选择:

  1. 使用 "authenticated encryption" (AE) or "authenticated encryption with associated data" (AEAD) cipher to do this. AE(AD) ciphers provide an "authentication tag" over the cipher text, either in a single pass or with a repeated process over the encrypted cipher text. Examples (probably available in whichever PHP cipher library you're using) are GCM, EAX, and CCM推荐,如果不验证认证标签,解密操作将失败,并且只需要一个共享秘密(密钥)。
  2. 您可以使用加密原语自行构建系统。这不太理想,因为你负责更多的独立部分,你需要管理更多的密钥(如果你有权访问 OMAC implementation,你可以使用相同的密钥),并且你的个人构造不受第三方审查各方(又名互联网的集体工作)。如果您遵循此路径,则需要牢记一些关键细节:
    • 使用强 hash-based message authentication code (HMAC),例如 HMAC/SHA-256、-384 或 -512。不要使用 SHA-1 或 MD5,因为它们很容易被暴力破解。
    • 在解密密文之前验证HMAC任何失败的HMAC意味着应丢弃整个密文。您可以将此(在生成端)记住为 Encrypt Then MAC,如果您搜索它,您会发现不遵循此建议是许多错误的来源加密漏洞和实施利用。
    • constant-time算法验证HMAC(即不使用short-circuit字符串相等比较,[中的默认值=63=]). PHP 提供 hash_equals to do this. Here's a quick explanation of timing attacks and a code review of a PHP example

对于任何一种选择,您都需要使用 URL-safe Base64 对生成的密文和身份验证标签进行编码,以避免数据丢失或损坏。如果您的消息格式没有严格按照包含的长度构建,则必须提前 pre-share 协议(即对于长度为 n 的消息 m 字节 -> 16 bytes IV | n-48 bytes cipher text | 32 bytes HMAC)。

最后说明:始终对使用密钥加密的每条消息使用唯一的 non-predictable IV。许多人忽略了这一点,因为它是 "easy to just use 0x00 * 16",但是如果使用相同的 IV 和密钥加密两条消息,任何用作 GCM 和 CCM 基础的流密码操作模式(如 CTR)都将失去基本的安全性.