这是理论上的一个,不仅适用于PHP,也可能适用于更多语言。
假设我使用mcrypt
库和AES-256
密码加密字符串。加密后的字符串现在看起来与þøÆ{”ò(ü´îÚÜÇW¹ËŸK¯L‘rø?ª¶!JF£º+Œ’Ú'‚
类似。
如果加密密钥在解密和加密事件之间发生变化,则解密结果显然毫无价值。
由于加密字符串至少对我来说包含随机字符,因此对它进行某种测试以确保它处于加密/解密状态并不容易。
我花了一些时间思考。 如何测试字符串是否已正确解密?
如果我在首先加密它之前在原始字符串中添加了一个小前缀,然后在解密时删除了该前缀,该怎么办?如果未找到此前缀,则可以安全地说解密失败。
这是处理此问题的合适方法吗?
答案 0 :(得分:2)
要测试数据完整性,您需要Message Authentication Code(MAC)。
有一些独立的MAC算法,看起来像带有密钥的哈希函数。非常标准的MAC算法是HMAC(使用散列函数)。
由于您还加密了数据,因此您需要使用内置MAC的加密模式;有一些这样的模式,例如GCM或EAX。这些模式适用于分组密码,通常是AES。
在加密之前为数据添加已知前缀或后缀是自制MAC。 MAC很微妙且容易出错。例如,如果您添加CRC32然后使用流密码(或CTR模式下的分组密码)进行加密,那么您正在复制the seven capital sins of WEP中的一个(特别参见第4节,CRC32-as-MAC)问题)。基本上,您的完整性检查不再能够抵抗主动攻击;你只是在检测无辜的错误,例如使用错误的密钥。
(不幸的是,似乎MCrypt不支持任何组合加密/ MAC模式。当使用--with-mhash
选项编译时,PHP本身提供mhash()
函数,该函数实现原始哈希和HMAC 。)
答案 1 :(得分:1)
如何测试字符串是否已正确解密?
“小前缀”的想法应该没问题;也是@CodeInChaos的优秀创意。除此之外,以某种定义的格式(如serialize()
或json_encode()
)存储字符串并且无法恢复它(unserialize()
,json_decode()
)将表明解密已损坏同样。