深入浅出AES算法

开发 开发工具 算法
高级加密标准(Advanced Encryption Standard,AES)是美帝2001年发布的块加密算法,AES是属于块加密算法框架中的一个组件,所以理解AES的关键是搞清楚块加密算法。下面,就一起来讲讲块加密算法工作原理。

AES算法

高级加密标准(Advanced Encryption Standard,AES)是美帝2001年发布的块加密算法,AES是属于块加密算法框架中的一个组件,所以理解AES的关键是搞清楚块加密算法。(块加密算法是一个“框”,AES只是“框”中的一个东西)

块加密算法工作原理

块加密算法也叫分组密码工作模式(block mode of operation)它会把明文按等长的块(Block)分组然后利用某种加密算法进行加密——AES就属于“某种加密算法”中的一种。用一幅图表示二者关系:

块加密算法和AES的关系

块加密算法有三个关键部分

  • 填充方式,负责把明文切分成一块一块的。块加密要求数据一定要符合块大小,以AES为例它规定每个数据块的大小是128个bit位(16字节),如果数据不足16字节那么必须**填充**到16字节。填充的数据是字节长度,比如一个5字节的块需要填充到16个字节,那么剩下的9个字节就全部写上09 09 09……。 PKCS5Padding和PKCS7Padding是分别出在不同规范的两个标准,PKCS5规定了块大小是8字节;PKCS7没有限制。由于AES已经限制了块的大小,所以它们两个在AES里面其实没有什么区别。所以在Java里面只提供了AES+PKC5Padding(AES+PKCS7Padding,这个说法不对,AES已经限制了块大小)。
  • 加密算法,负责对每一块的明文进行加密。对算法输入明文和密钥,算法输出加密后的密文块,常见的算法是AES、DES。
  • 工作方式,块加密非常灵活利用不同的工作模式可以实现**并行、密文可变(每次加密得到的密文都不一样)、容错**

块加密算法的五种工作方式

按照块加密算法的不同工作模式常见的有5种(为了简化问题我只贴加密过程):

  • 电子密码本(ECB,Electronic codebook)
  • 电子密码本

Key是密钥,Plaintext是明文,中间的Block Cipher Encryption是加密算法(比如AES就是其中一种)。密钥和明文作为输入经过加密之后得到密文——Ciphertext。

ECB工作模式非常简单,可以并行处理;一个线程负责把数据切分成N块后由N个线程同时进行加密。它的缺点是同样的密钥每次执行加密出来的数据都是相同的。正常人看——比如我,这太正常了,但是“密码专家”们认为这太弱鸡了(囧)。所以他们设计了一种特别的算法,通过一个叫“初始向量(IV,Initialization Vector)”的变量让每次进行加密得到的密文都不一样(即便密钥相同)。剩下的4种块工作模式都属于这种牛B的类型。

  • 密码块链接(CBC,Cipher-block chaining)
  • 密码块链接(CBC,Cipher-block chaining)

这里的输入多了一个叫Initialization Vector(IV)的变量;明文和IV异或之后通过作为加密算法的一个变量输入,密钥作为另一个变量输入。

CBC加密算法是一个串行算法,第二块的加密依赖于***块密文作为IV。所以计算它的时候只能按部就班一块一块的计算。

  • 密文反馈(CFB,Cipher feedback)
  • 密文反馈(CFB,Cipher feedback)

之前的块加密都没有解决容错问题——如果我一个数据块坏掉了那么能不能解密出其余的数据块。于是就有了CFB工作模式,注意观察上图,解密的时候如果***个密文块损坏那么可以无视这块内容,直接用第二个密文作为输入对第三个密文块进行解密。

  • 输出反馈模式(OFB,Output feedback)
  • 输出反馈模式(OFB,Output feedback)

CBC虽然狂屌炸(每次都能算出不同的密文)但是不能并行,对于“时间就是金钱”的计算机来说是无法容忍的。于是就有了***次改进——OFB。

注意IV和密钥经过加密后这里是可以并行的,其中一个线程用于和明文的异或;一个线程可以立马计算“下次”加密。

  • 计数器模式(CTR,Counter mode)
  • 计数器模式

OFB算法的并行度太低,仅仅实现一部分并行,于是就有了第二次改进——CTR算法,同时保证了并行度和密文可变性。

CTR算法中的IV变成了两部分,***个是Nonce可以是一个随机序列,第二部分是计数器(Countter),是一个递增的数字。于是加密的时候通过组合Nonce和计算器就可以对得到有规律但是不相同的(每次密文都不同的关键是IV的可变)“IV”。

总结

从三个维度理解五种工作模式——密文是否固定、是否可以并行、有没有容错

  • ECB密文固定,全并行
  • CBC密文可变,不可并行
  • CFB密文容错,密文可变,不可并行
  • OFB密文可变,部分并行
  • CTR密文可变,全并行

需要注意的是除非数据量特别大否则我们不必在乎是否并行;容错在小数据量的时候也凸显不出效果,所以CBC一般是***的选择。

如何跨语言

很多朋友都碰到一个语言写的AES加密在另个一语言解密不了的问题,究其原因是由于根本没有理解AES的工作模式(可能就是Google了一下AES加密,然后代码贴上收工)。所以我觉得跨语言的***步不是找到一种能在所有语言通用的工作模式——所有工作模式每个语言几乎都支持;而是搞清楚你加密出来的数据是那种工作模式,有没有用到IV?IV是通过什么方式传递给对方的?

比如下面的Java代码:

我使用了CBC加密模式,这种模式涉及到IV,我们可以用一个固定的IV(比如用key作为IV)——但是意味着没有了CBC的好处,密文可变。所以我用一个随机16字节作为IV,返回的时候把它作为***个数据块;解密的时候只要取出***个数据块作为IV,然后再对余下的数据进行解密。

如果我们不指定IV参数(init函数的第三个参数),那么iv就是一个随机数。Java是不会主动把IV附加到密文上,所以这种加密出来的数据是谁也没有办法解出来的。

【本文是51CTO专栏作者“邢森”的原创文章,转载请联系作者本人获取授权】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2021-03-16 08:54:35

AQSAbstractQueJava

2011-07-04 10:39:57

Web

2012-05-21 10:06:26

FrameworkCocoa

2019-01-07 15:29:07

HadoopYarn架构调度器

2021-07-20 15:20:02

FlatBuffers阿里云Java

2022-09-26 09:01:15

语言数据JavaScript

2022-05-06 07:19:11

DOMDiff算法

2022-12-02 09:13:28

SeataAT模式

2018-11-09 16:24:25

物联网云计算云系统

2009-11-18 13:30:37

Oracle Sequ

2009-11-30 16:46:29

学习Linux

2019-12-04 10:13:58

Kubernetes存储Docker

2019-11-11 14:51:19

Java数据结构Properties

2022-01-11 07:52:22

CSS 技巧代码重构

2021-04-27 08:54:43

ConcurrentH数据结构JDK8

2012-02-21 13:55:45

JavaScript

2022-11-09 08:06:15

GreatSQLMGR模式

2022-10-31 09:00:24

Promise数组参数

2021-07-19 11:54:15

MySQL优先队列

2010-07-16 09:11:40

JavaScript内存泄漏
点赞
收藏

51CTO技术栈公众号