/首页
/开源
/关于
安全篇之永强再次教你加解密:对称篇(二)
发表@2019-02-02 14:38:17
更新@2023-01-21 22:47:40
> “我们历经千辛万苦,摸打滚爬过数不清的错误,发射了不知道多少枚长征系列,耗费了一代航天人的心血,终于看到了地球与月亮通信的曙光,然后就在五分钟,我们惊讶地发现,原来老王的smartmesh技术早就实现了,甚至连地球文明与外形文明的通信都给出了完美的解决方案...” ------ 尼古拉斯\*永强 众所周知,作为精通各种技术表演的我早就已经不屑于采用ppt的方式吹牛了,一般我都是直接上机操作表演,当然了,程序都是提前写好了的,全是mock的假数据,脚本实现自动化,无论谁来操作都是流畅的,一切都是完美的! 作为一个追求完美的人,我还得继续接着吹上次聊到结尾,好像是遗留了两个问题: - ecb、cfb、cbc等这些后缀是什么意思 - iv向量又是什么意思 鉴于DES和3DES已经属于不建议使用的方法了,所以这次我们直接用AES加密进行装逼表演,比如下面这坨代码,你们复制粘贴走运行一下: ```php c1391e34caf38f8c2a477cbda3772533c1391e34caf38f8c2a477cbda3772533d96aa42b59151a9e9b5925fc9d95adaf : 96 分析一下上面代码:这次我们选用的加密方法是AES-128-ECB,这个128是什么意思?128就是密钥长度的意思,128bit;如果你留心的话,还会注意到有aes-192-ecb和aes-256-ecb,其实就是指加密密钥长度为192bit、256bit,然后是值得注意的一个地方是: > $enc_data = openssl_encrypt( $data, $my_method, $key, OPENSSL_RAW_DATA ); 最后一个参数是OPENSSL_RAW_DATA,如果选用这个option的话,经过加密后的数据会是奇怪的二进制数据,无法直接通过文本方式查看,所以要看的话必须先使用bin2hex函数处理一下。 注意了哈,我选的这个密钥1234567812345678是有特殊用意的,这个密钥的长度是16字节也就是128bit,而我们选用的aes加密方法中要求的密钥长度就是128bit,那么我们尝试将密钥增加几位变成:1234567812345678abc,***然后其他代码不做任何改动***,再次执行加密,结果如下: > c1391e34caf38f8c2a477cbda3772533c1391e34caf38f8c2a477cbda3772533d96aa42b59151a9e9b5925fc9d95adaf : 96 就是说用“1234567812345678”和“1234567812345678abc”加密后的数据都是一样的。 #### 看起来如果我们选用128bit密钥长度的话,一旦密钥长度超过128bit后面多余的部分会被直接无视掉~~~ 然后我们再尝试将密钥“1234567812345678”缩短一个字节,改成“123456781234567”,其他地方代码不做任何改动,运行一波儿,结果如下: > c202e5b1dc36c3147e50d02df7ab700cc202e5b1dc36c3147e50d02df7ab700cda89b056d926d3fea2e59ffc552b1d98 : 96 这次不行了,已经不一样了~ 然后,我们将注意力放到明文和密文上来: > 明文: 12345678abcdxxoo12345678abcdxxoo 密文:c1391e34caf38f8c2a477cbda3772533c1391e34caf38f8c2a477cbda3772533d96aa42b59151a9e9b5925fc9d95adaf 仔细观察,有一个比较屌的地方,你们感受一下: > c1391e34caf38f8c2a477cbda3772533 | c1391e34caf38f8c2a477cbda3772533 | d96aa42b59151a9e9b5925fc9d95adaf ![](https://ti-node.com/static/upload/6497323789523615745) #### 卧槽,竟然有前两段是一样的!???卧槽。。。 。。。 仔细看了一把明文12345678abcdxxoo12345678abcdxxoo,卧槽,好像: > 12345678abcdxxoo | 12345678abcdxxoo 难道说明文“12345678abcdxxoo”被密钥“1234567812345678”加密后后的密文就是“c1391e34caf38f8c2a477cbda3772533”? #### 时机已然成熟了!是时候继续深入装逼了!为什么会出现这个结果?现在我们开始说“ecb、cfb、cbc等这些后缀是什么意思”。 你若有所思的猜测到:“难道说对称加密的时候,都是将明文先分块,然后再分别对分块加密?”,我欣慰地看着你说:“嗯,是的,肯定是,不然老子往下没法写了,我特么都快编不下去了...” - DES和3DES会将明文以64bit(8字节)作为一个单元进行分组; - AES则会将明文以128bit(16字节)作为一个单元进行分组; - 无论是AES还是DES,当最后一个分组的数据长度不满足分组标准长度的时候,会用某种填充方式进行填充; - AES对一个16字节分组加密完毕后,分组大小依然为16字节;DES也一样 比如说这段明文“12345678abcdxxoo12345678abcdxxoo”,一共是32字节,理论上说就会被先按照16字节分组:“12345678abcdxxoo”是一组,剩下的“12345678abcdxxoo”是另外一组,我们用程序验证一下: ```php AES和DES以及3DES这种加密方式被称为分组密码,分组密码每次只能加密固定长度的明文,所以如果明文很长的话,就需要轮流为每个分组明文进行加密,AES的分组长度是128bit,而DES的分组长度为64bit;如果一旦需要对多个分组进行轮流加密,加入明文被分成了三个明文分组,那么就需要对三个明文进行迭代加密(粗暴理解就是轮流加密),然而会有很多种不同的迭代方式,这种不同的迭代方式专业名词就叫“模式”,这些模式有:ECB、CBC、OFB、CFB、CTR... ... PS:⚠️对明文进行分组的方式是固定的,唯一不同的就是分组长度不一样而已;模式是指对多个明文从第一个开始轮流加密到最后一个的这个过程,是怎么轮流执行的。