加密:测试字符串是否被正确解密?
这里的理论不仅适用于PHP,也适用于更多语言。加密:测试字符串是否被正确解密?
假设我使用mcrypt
库和AES-256
密码加密字符串。加密的字符串现在看起来类似于þøÆ{”ò(ü´îÚÜÇW¹ËŸK¯L‘rø?ª¶!JF£º+Œ’Ú'‚
。
如果加密密钥在解密和加密事件之间改变,解密的结果显然是毫无价值的。
由于加密的字符串至少包含我自己的随机字符,所以对其进行某种测试并不容易,以确保它处于加密/解密状态。
我花了一些时间思考。 我如何测试一个字符串已被正确解密?
如果我在首先对原始字符串进行加密之前附加了一个小前缀,然后在解密时删除此前缀,该怎么办?如果未找到该前缀,则说解密失败是安全的。
这是处理这个问题的适当方法吗?
要测试数据完整性,您需要一个Message Authentication Code(MAC)。
有几个独立的MAC算法,看起来像一个密钥的散列函数。非常标准的MAC算法是HMAC(它使用散列函数)。
由于您还对数据进行了加密,您将需要使用内置MAC的加密模式;有几种这样的模式,例如GCM或EAX。这些模式适用于分组密码,通常为AES。
加密前为数据添加一个已知的前缀或后缀是自制的MAC。 MAC很微妙且容易出错。例如,如果您添加一个CRC32,然后使用流密码(或CTR模式下的分组密码)进行加密,则您正在复制the seven capital sins of WEP中的一个(有关CRC32-as-MAC问题,请参见第4节)。基本上你的完整性检查不再能抵抗主动攻击;你只是在侦测无辜的错误,比如使用错误的键。
(不幸的是,似乎在与--with-mhash
选项编译mcrypt的不支持任何混合加密/ MAC模式。PHP本身,提供了mhash()
功能,同时实现了原始散列和HMAC)
我怎样才能测试一个字符串已被正确解密?
“小前缀”的想法应该没问题;也@CodeInChaos的优秀创意。除此之外,以某种定义的格式存储字符串(如serialize()
或json_encode()
)并且无法恢复它(unserialize()
,json_decode()
)也可能表示解密破坏。
你可以包括你的明文的散列(如sha-1)而不是简单的前缀。这样你就可以把完整性检查作为奖励。 – CodesInChaos 2011-02-22 19:03:32
@Code这是一个好主意。散列必须后跟一个定义的字符来标记边界 – 2011-02-22 19:09:09
关于你的方法,如果你能找到一个字符串$ a,那么对于每个可能的字符串$ b,$ a的编码都是安全的。 $ b永远不会以$ a开始。 – greg0ire 2011-02-22 19:09:56