在 PHP 中使用 aes-256-gcm 进行OpenSSL 加密时,是tag_length
编码器选择的值还是由方法选择并像使用一样返回给指针tag
?它读取的值可以在 4 到 16 之间。加密函数中输入的 tag_length 是否保证是返回的标签的长度?
此外,如何aad
使用(“额外的经过验证的数据”)以及为什么要使用它?
谢谢。
在 PHP 中使用 aes-256-gcm 进行OpenSSL 加密时,是tag_length
编码器选择的值还是由方法选择并像使用一样返回给指针tag
?它读取的值可以在 4 到 16 之间。加密函数中输入的 tag_length 是否保证是返回的标签的长度?
此外,如何aad
使用(“额外的经过验证的数据”)以及为什么要使用它?
谢谢。
GCM 是经过认证的加密,可保证机密性和真实性。对于后者,使用认证标签。
真实性保证意味着数据(密文、IV、AAD)不能在不被察觉的情况下被更改(通过解密期间的认证标签进行真实性检查)。
身份验证标签在加密过程中自动生成,可通过 引用
$tag
。标签长度可以用 指定$tag_length
,默认情况下为 16 字节,s。openssl_encrypt()
根据 GCM 规范(s. NIST SP 800-38D,sec. 5.2.1.2 输出数据),允许的标签大小为 16、15、14、13、12 以及特殊情况下的 8 和 4 字节(与此不同,PHP/OpenSSL 支持 4 到 16 字节之间的所有大小)。标签长度越大,安全性越高。在解密过程中,必须指定标签,s.
openssl_decrypt()
。标签(以及 IV)不是秘密的,并与密文(和 IV)一起传递到解密方,通常是连接在一起的,例如IV|ciphertext|tag
。AAD(附加认证数据)是经过认证但未加密的数据(这可以是任何您想要确保不会被更改的信息,但它不是秘密,因此不需要加密)。
示例(使用 12 字节标签和 AAD 的 GCM 加密/解密):
编辑-关于评论中的问题:
为什么标签不是秘密的?
身份验证标签 (或MAC ) 本质上是一种校验和,它是使用特定算法和密钥从密文、IV 和 AAD 加密时生成的。解密时,会重新计算标签并将其与加密标签进行比较 (s. NIST SP 800-38D , sec. 7 GCM Specification )。
如果加密和解密的标签相同,则身份验证成功。相反,如果攻击者操纵了数据 (密文和/或 IV 和/或 AAD),则解密过程中会生成不同的标签,从而揭示对数据的操纵。
标签不是秘密,因为攻击者无法伪造它,因为攻击者没有密钥。因此,标签可以与密文一起传递给解密方。
为什么 IV 不秘密且随机?
IV 的目的是防止相同明文的加密生成相同的密文(另请参阅ECB 模式中的语义安全性
)。这意味着每次加密都必须使用不同的密钥/IV 对。 因此,对于固定密钥(正常情况),每次加密都必须使用不同的 IV。否则,如前所述,相同的明文会生成相同的密文,并且根据模式的不同,还会产生或多或少严重的漏洞(例如,对基于 CTR 的模式(如 GCM)重用密钥/IV 对是一个严重的漏洞,请参见此处)。每次加密随机生成 IV 是每次加密生成不同密钥/IV 对的常用方法。
由于解密需要 IV,因此算法的设计使得 IV 不必是秘密的,或者换句话说,已知的 IV 不会降低算法的安全性。因此,IV 可以与密文一起传递到解密端。