当前位置: 首页 > 科技观察

AES算法_0

时间:2023-03-17 15:48:57 科技观察

AES算法高级加密标准(AdvancedEncryptionStandard,AES)是美国于2001年发布的一种块加密算法。AES是块加密算法框架的一个组成部分,所以理解AES的关键是图出块加密算法。加密演算法。(块加密算法是一个“盒子”,AES只是“盒子”里的东西)。块加密算法的工作原理。块加密算法也称为块操作模式。Block)组,然后使用某种加密算法进行加密——AES是“某些加密算法”之一。用一张图来说明两者的关系:分块加密算法有3个关键部分:填充法,负责将明文切块。块加密要求数据必须符合块大小。以AES为例,它规定每个数据块的大小为128位(16字节)。如果数据小于16字节,则必须填充到16字节。.填充的数据是字节长度,比如一个5字节的块需要填充到16字节,那么剩下的9个字节全部写成090909....PKCS5Padding和PKCS7Padding是两个不同规范的标准。PKCS5规定块大小为8字节;PKCS7没有限制。由于AES对blocksize做了限制,所以两者在AES中其实没有区别。所以Java中只提供了AES+PKC5Padding(AES+PKCS7Padding,这个说法是错误的,AES已经限制了blocksize)。加密算法负责对每个块的明文进行加密。将明文和密钥输入算法,算法输出加密后的密文块。常见的算法是AES和DES。工作模式,块加密非常灵活利用不同的工作模式可以实现**并行、可变密文(每次加密得到的密文不同)、容错**块加密算法的五种工作模式根据块加密算法有常见的5种不同的工作模式(为了简化问题,我只贴出加密过程):电子密码本(ECB,Electroniccodebook)Key是密钥,Plaintext是明文,中间的BlockCipherEncryption是加密算法(例如,AES就是其中之一)。将密钥和明文作为输入进行加密,得到密文——Ciphertext。ECB的工作方式非常简单,可以并行处理;一个线程负责将数据分成N个块,然后由N个线程同时加密。它的缺点是每次执行同一个密钥加密的数据都是一样的。对于普通人——比如我来说,这是完全正常的,但“密码学家”认为它太弱了(囧)。于是他们设计了一种特殊的算法,通过一个叫做“初始化向量(IV,InitializationVector)”的变量,使得每次加密得到的密文都不一样(即使密钥相同)。其余四种区块工作模式都属于这种牛B。密码区块链(CBC,Cipher-blockchaining)这里多了一个变量叫做InitializationVector(IV)input;明文和IV异或作为加密算法的一个变量输入,密钥作为另一个变量输入。CBC加密算法是一个串行算法,第二个块的加密依赖于第一个块的密文作为IV。所以在计算的时候,只能一步步计算。密码反馈(CFB,Cipherfeedback)之前的块加密并没有解决容错问题——如果我的一个数据块坏了,我能否解密其余的数据块。于是就有了CFB工作模式,注意观察上图,如果解密时第一个密文块损坏,可以忽略这个内容,直接用第二个密文作为输入,解密第三个密文块。输出反馈方式(OFB,Outputfeedback)CBC虽然很疯狂(每次都可以计算出不同的密文),但是无法并行化,这对于“时间就是金钱”的计算机来说是无法容忍的。于是就有了第一个改进——OFB。注意IV和key加密后,这里可以并行,其中一个线程与明文进行XOR;一个线程可以立即计算出“下一个”加密。计数器模式(CTR,Countermode)OFB算法的并行度太低,只实现了一部分的并行性,于是有了第二种改进——CTR算法,它同时保证了并行性和密文可变性。CTR算法中的IV变成两部分,第一部分是Nonce可以是一个随机序列,第二部分是计数器(Counter),是一个递增的数。因此,在加密时,结合Nonce和计算器,可以得到一个有规律但不同的“IV”(每次不同密文的关键就是变量IV)。综上所述,从三个维度理解五种工作模式——密文是否固定,是否可以并行,是否容错。并行OFB密文是可变的,部分并行CTR密文是可变的。需要注意的是,除非数据量特别大,否则我们不需要关心并行度;容错在数据量小的时候无法凸显效果,所以CBC一般是***sChoice。如何跨语言很多朋友都遇到过用一种语言写的AES加密无法用另一种语言解密的问题。原因是他们根本不了解AES的工作模式(可能谷歌AES加密,然后贴代码收工。)。所以我认为跨语言的第一步并不是要找到一种所有语言都可以使用的工作模式——几乎所有的语言都支持所有的工作模式;但是要弄清楚你的加密数据是什么工作模式,有没有用到IV?IV是如何传递给对方的?比如下面的Java代码:我使用的是CBC加密方式,其中涉及到IV,我们可以使用固定的IV(比如用密钥作为IV)——但是这意味着没有CBC的好处,并且密文是可变的。所以我用了一个随机的16字节作为IV,返回的时候作为第一个数据块;解密的时候,我只需要取出第一个数据块作为IV,然后再解密剩下的数据。如果我们不指定IV参数(init函数的第三个参数),那么iv就是一个随机数。Java不会主动给密文附加IV,所以加密后的数据谁也无法解密。【本文为专栏作家“行森”原创文章,转载请联系作者获得授权】点此阅读更多本作者好文