des奇偶校验

今天又摊上件怪事,测试人员反映,以密钥000加密导出的文件用解密工具以密钥111竟然也能顺利解成功,进一步测试发现,密钥中0与1、2与3、4与5、6与7、8与9都是等价的。

我走查了加解密相关的代码,没有发现有不当的地方,加解密均采用的3DES算法,使用CBC计算模式,密钥KEY由页面输入,最长24个字节,如不足则用0x80补齐,IV均取8字节的0x08,不同的是加密直接调的openssl命令行,而解密使用的是openssl编程接口,原理上这不应该有什么影响。

为了弄清楚真相,我找了一小段文本,照着加密时使用的命令行对其做3DES加密,然后用原密钥解密,得到了正确的明文,再改用所谓的等价密钥解密,确实也能正确解出。

[root@dev ~]# key1=303030303030303030303030303030303030303030303030
[root@dev ~]# key2=313131313131313131313131313131313131313131313131
[root@dev ~]# iv=0808080808080808
[root@dev ~]# echo "chenfy" | openssl enc -a -des-ede3-cbc -K $key1 -iv $iv
Uu4B8WrNYCs=
[root@dev ~]# echo "Uu4B8WrNYCs=" | openssl enc -d -a -des-ede3-cbc -K $key1 -iv $iv 
chenfy
[root@dev ~]# echo "Uu4B8WrNYCs=" | openssl enc -d -a -des-ede3-cbc -K $key2 -iv $iv
chenfy

由此可见这并不是代码实现问题,而是算法本身的原因,这让我很费解,因为3DES作为广泛使用的对称加密算法,怎么可能会有这么低级的问题。我花时间专门去研究了下DES与3DES算法的原理,终于找到了问题的根源——奇偶校验。

何谓奇偶校验?在通信过程中,有可能出现数据的某一位发生0-1翻转的情况,虽然是小概率事件,但只要出现了就可能导致整块数据都是错的,这在密文传输场景尤为明显。为了避免这种事故,可将每个字节的最后一位作为奇偶校验位,使得每个字节的二进制表示都含有奇数个1或者偶数个1,而奇偶校验位本身不参与构成数据。数据接收方收到数据后做相同的校验,如不满足校验,说明通信过程中发生了意外,可要求对方重新发送。由于单个字节中两个位同时发生改变几乎是不可能事件,这种做法非常简单有效。

DES密钥就满足奇校验,密钥长度为8个字节,每个字节的最后一位是奇校验位,使得其二进制表示含有奇数个1,换句话说,DES密钥总共有64位,其中第8、16、24、32、40、48、56、64位是奇校验位,真正用于构成密钥数据做加解密的是每个字节的前7位,总共56位。上述列举的0与1、2与3等都是只在奇校验位上不同,因此作为DES密钥是等价的,能正确解密也就不足为奇了。

Table of Contents