PHP 的 mcrypt 扩展是否兼容 FIPS 197?
我正在使用以下加密代码,它的工作方式就像一个魅力,但我必须验证它是否符合 FIPS 197,否则合法会杀了我。
mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $plaintext, MCRYPT_MODE_ECB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
MCRYPT_RAND))
和
mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SALT, $plaintext, MCRYPT_MODE_ECB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
MCRYPT_RAND))
I'm using the following encryption code which works like a charm, but I have to validate that it's FIPS 197 compliant otherwise Legal will kill me.
mcrypt_encrypt(MCRYPT_RIJNDAEL_256, SALT, $plaintext, MCRYPT_MODE_ECB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
MCRYPT_RAND))
and
mcrypt_decrypt(MCRYPT_RIJNDAEL_256, SALT, $plaintext, MCRYPT_MODE_ECB,
mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB),
MCRYPT_RAND))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
FIPS 197 仅指定了 Rijndael 算法,并未指定其实现。所以是的,它是合规的。
然而,NIST SP 800-38A 中指定了实现方式。
我不知道其余的(明文填充、PRNG 的强度等),但在 99% 的 Rijndael 实现中,ECB 是一件非常非常糟糕的事情,因此不推荐。
FIPS 197 only specifies the Rijndael algorithm, not the implementation. So yes, it is compliant.
The implementation however is specified in NIST SP 800-38A.
I do not know about the rest (plaintext padding, strength of the PRNG, etc.), but ECB is a very, very bad thing to do in 99% of Rijndael's implementations and thus not recommended.
取决于你对“合规”的定义。它是否符合 FIPS 197 规定的所有规则 - 是的,我相信是的。
它未经过 FIPS 197 验证。经过验证的实施意味着它已经过 NIST / CST 实验室的专门测试,并经过认证符合 FIPS pub 197。您可以使用 此列表,获取经过 FIPS 197 验证的所有供应商和产品的列表。
Depends on what your definition of "compliant". Does it comply with all of the rules set out with FIPS 197 - yes I believe so.
It is not FIPS 197 validated. A validated implementation means it's been specifically tested by NIST / CST Labs and certified to comply with FIPS pub 197. You can use this list for a list of all vendors and products that are FIPS 197 validated.
Mcrypt 的
RIJNDAEL_256
算法是 Rijndael 算法的版本,块大小为 256 位。 AES(FIPS 197 定义的)仅具有 128 位块大小(以及三种不同密钥大小)的版本。所以不,你在这里没有使用 AES。请改用 RIJNDAEL_128,这与 AES 相同。
您的代码还存在其他问题:
如果您使用同一密钥加密多个块,则永远不应该使用 ECB。所以,永远不会。请改用一种安全的操作模式,例如 CBC 或 CTR。
正如 CodeInChaos 所评论的,您通常希望确保您还具有真实性,而不仅仅是机密性(并且根据您的协议,您甚至可能需要身份验证以保证机密性)。因此,在您的消息中添加 MAC,或者使用同时提供身份验证和机密性的操作模式(例如 CCM 或 GCM) - 不确定 mcrypt 中包含哪些内容。
您生成一个关于加密(好)和解密(坏)的随机初始化向量。这对于 ECB 来说并不重要,因为它不使用初始化向量,但在任何其他模式下,您都会为这两个操作获得不同的初始化向量,这意味着解密将得到不同的结果。使用 CBC,只有第一个块将是垃圾,而使用 CTR,所有内容都将是垃圾(并且 CCM/GCM 将简单地报告“失败”)。
由于初始化向量不需要保密(只是不可预测或不可重复,具体取决于模式),因此习惯将其与消息一起发送(作为前缀),或者派生它(双方)来自一个共同的秘密(就像 SSL/TLS 中的第一个初始化向量,它们源自主秘密,就像加密密钥和 MAC 密钥一样)。
Mcrypt's
RIJNDAEL_256
algorithm is the version of the Rijndael algorithm with 256 bit block size. AES (which is what FIPS 197 defines) has only versions with 128-bit block size (and three different key sizes).So no, you are not using AES here. Use RIJNDAEL_128 instead, which is the same as AES.
There are other things wrong with your code:
You should never use ECB if you are encrypting more than one block with the same key. So, never. Use a secure mode of operation instead, like CBC or CTR.
As CodeInChaos commented, you normally want to make sure you also have authenticity, not only confidentiality (and depending on your protocol, you might even need authentication for confidentiality). So, add a MAC to your message, or use a mode of operation which also gives authentication together with confidentiality (like CCM or GCM) - not sure which ones are included in mcrypt.
You generate a random initialization vector on encryption (good) and decryption (bad). This doesn't matter for ECB, since it doesn't use an initialization vector, but with any other mode you'll get a different initialization vector for both actions, meaning that decryption will get different results. With CBC only the first block will be garbage, while with CTR everything will be garbage (and CCM/GCM will simply report "fail").
As the initialization vector doesn't need to be secret (just non-predictable or non-repeating, depending on the mode), it is custom to either send it together with the message (as a prefix), or to derive it (on both sides) from a common secret (like the first initialization vectors in SSL/TLS, which are derived from the master secret, just as the encryption keys and MAC keys).