密码算法详解——AES

0 AES简介

  咱们知道数据加密标准(Data Encryption Standard: DES)的密钥长度是56比特,所以算法的理论安全强度是256。但二十世纪中后期正是计算机飞速发展的阶段,元器件制造工艺的进步使得计算机的处理能力愈来愈强,DES将不能提供足够的安全性。1997年1月2号,美国国家标准技术研究所(National Institute of Standards and Technology: NIST)宣布但愿征集高级加密标准(Advanced Encryption Standard: AES)[3],用以取代DES。AES获得了全世界不少密码工做者的响应,前后有不少人提交了本身设计的算法。最终有5个候选算法进入最后一轮:RijndaelSerpentTwofishRC6和MARS,下图分别为其中的5位做者。最终通过安全性分析、软硬件性能评估等严格的步骤,Rijndael算法获胜。git

  Rijndael由比利时两位很是著名的密码学家Joan DaemenVincent Rijmen设计。Rijndael是一个分组密码算法族,其分组长度包括128比特、160比特、192比特、224比特、256比特,密钥长度也包括这五种长度,可是最终AES只选取了分组长度为128比特,密钥长度为128比特、192比特和256比特的三个版本。本文主要结合AES-128进行介绍,AES-196和AES-256的思路基本同样,只是密钥扩展算法的过程会稍有不一样,加解密的轮数会适当增长,但加解密的操做都是同样的。另外,本文只对AES算法的各个模块、基本原理进行介绍,旨在加深对算法流程、密码算法实现的了解。在正式软件运用中并不推荐本身编写代码,不少开源项目如Linux,OPENSSL,SRTP等都有很是高效的实现。因为数学知识的缺陷,本文不介绍算法安全性分析相关的知识,有兴趣的读者能够自行阅读相关文献。github

  AES是一个分组密码,属于对称密码范畴,AES算法的模块在对称密码领域特别是分组密码领域常有使用。算法

1 算法流程

  AES加密算法涉及4种操做:字节替代(SubBytes)、行移位(ShiftRows)、列混淆(MixColumns)和轮密钥加(AddRoundKey)。下图给出了AES加解密的流程,从图中能够看出:1)解密算法的每一步分别对应加密算法的逆操做,2)加解密全部操做的顺序正好是相反的。正是因为这几点(再加上加密算法与解密算法每步的操做互逆)保证了算法的正确性。加解密中每轮的密钥分别由种子密钥通过密钥扩展算法获得。算法中16字节的明文、密文和轮子密钥都以一个4x4的矩阵表示。数组

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.1 字节替代

  字节代替的主要功能是经过S盒完成一个字节到另一个字节的映射。S盒的详细构造方法能够参考文献[4]。这里直接给出构造好的结果,下图(a)为S盒,图(b)为S-1(S盒的逆)。S盒用于提供密码算法的混淆性安全

  S和S-1分别为16x16的矩阵,完成一个8比特输入到8比特输出的映射,输入的高4-bit对应的值做为行标,低4-bit对应的值做为列标。假设输入字节的值为a=a7a6a5a4a3a2a1a0,则输出值为S[a7a6a5a4][a3a2a1a0],S-1的变换也同理。网络

  例如:字节00000000B替换后的值为(S[0][0]=)63H,再经过S-1便可获得替换前的值,(S-1 [6][3]=)00Hide

1.2 行移位

  行移位是一个4x4的矩阵内部字节之间的置换,用于提供算法的扩散性函数

  1) 正向行移位性能

  正向行移位用于加密,其原理图以下。其中:第一行保持不变,第二行循环左移8比特,第三行循环左移16比特,第四行循环左移24比特。优化

  假设矩阵的名字为state,用公式表示以下:state’[i][j] = state[i][(j+i)%4];其中i、j属于[0,3]。

  2) 逆向行移位

  逆向行移位便是相反的操做,即:第一行保持不变,第二行循环右移8比特,第三行循环右移16比特,第四行循环右移24比特。

  用公式表示以下:state’[i][j] = state[i][(4+j-i)%4];其中i、j属于[0,3]。

1.3 列混淆

  列混淆:利用GF(28)域上算术特性的一个代替,一样用于提供算法的扩散性

  1) 正向列混淆

  正向列混淆的原理图以下:

  根据矩阵的乘法可知,在列混淆的过程当中,每一个字节对应的值只与该列的4个值有关系。此处的乘法和加法都是定义在GF(28)上的,须要注意以下几点:

    1) 将某个字节所对应的值乘以2,其结果就是将该值的二进制位左移一位,若是原始值的最高位为1,则还须要将移位后的结果异或00011011;[1]

      英文原文描述以下:In particular, multiplication of a value by x (i.e., by {02}) can be implemented as a 1-bit left shift followed by a conditional bitwise XOR with (0001 1011) if the leftmost bit of the original value (prior to the shift) is 1.

    2) 乘法对加法知足分配率,例如:07·S0,0=(01⊕02⊕04)·S0,0= S0,0⊕(02·S0,0)(04·S0,0)

    3) 此处的矩阵乘法与通常意义上矩阵的乘法有所不一样,各个值在相加时使用的是模28加法(异或运算)。

  下面举一个例子,假设某一列的值以下图,运算过程以下:

    

  

  在计算02与C9的乘积时,因为C9对应最左边的比特为1,所以须要将C9左移一位后的值与(0001 1011)求异或。同理能够求出另外几个值。

  2) 逆向列混淆

  逆向列混淆的原理图以下:

 

  因为:

 

  说明两个矩阵互逆,通过一次逆向列混淆后便可恢复原文。

1.4 轮密钥加

  这个操做相对简单,其依据的原理是“任何数和自身的异或结果为0”。加密过程当中,每轮的输入与轮子密钥异或一次;所以,解密时再异或上该轮的轮子密钥便可恢复。

1.5 密钥扩展算法

  密钥扩展的原理图以下:

 

  密钥扩展过程说明:

    1)  将种子密钥按图(a)的格式排列,其中k0、k1、……、k15依次表示种子密钥的一个字节;排列后用4个32比特的字表示,分别记为w[0]、w[1]、w[2]、w[3];

    2)  按照以下方式,依次求解w[j],其中j是整数而且属于[4,43];

    3)  若j%4=0,则w[j]=w[j-4]⊕g(w[j-1]),不然w[j]=w[j-4]⊕w[j-1];

  函数g的流程说明:

    a)  将w循环左移8比特;

    b)  分别对每一个字节作S盒置换;

    c)  与32比特的常量(RC[j/4],0,0,0)进行异或,RC是一个一维数组,其值以下。(RC的值只须要有10个,而此处用了11个,实际上RC[0]在运算中没有用到,增长RC[0]是为了便于程序中用数组表示。因为j的最小取值是4,j/4的最小取值则是1,所以不会产生错误。)

      RC = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36}

1.6 小结

  密码算法要求是可逆的,这样解密算法才能正确的恢复明文。拿AES来讲,在密钥固定的状况下,明文和密文在整个输入空间是一一对应的。所以算法的各个部件也都是可逆的,再将各个部件的操做顺序设计成可逆的,密文就能正确的解密了。

2 源码

  本身写了一份AES-128的实现代码,放在Github上;另一份AES代码实现了3种密钥长度的算法,和标准文档彻底保存一致,没有作任何优化,有兴趣能够看看。

  AES中列混淆部分设计有限域乘法操做,在运行中须要消耗较多的时间。如今的计算平台都拥有丰富的软件资源(RAM、Flash等),所以AES的软件实现通常都会采用查表的方式,将字节替代、行移位、列混淆合在一块儿查表,大概消耗8-10K字节的存储空间,但效率很是之高。

  在硬件上,为了减小实现面积,能够经过对解密的操做进行适当调换,这样解密操做能够复用加密的电路。

3 扩展

SIMD [10]:单指令流多数据流指令,最经常使用的包括SSE、SSE二、AVX、AVX512 [5] 等,如今不少Intel和AMD的处理器都支持。SIMD操做可以很大地提升效率,一些项目中都有用到,好比libsodium [6](A modern and easy-to-use crypto library)、FastMemcpy [7] (Speed-up over 50% in average vs traditional memcpy in gcc 4.9 or vc2012 )、hamming_weight [8] (C library to compute the Hamming weight of arrays)等。

AES-NI [9]:AES硬件指令,可以很快地实现AES加解密,大部分Intel处理器、AMD处理器支持。

4 参考文献

[1] William Stallings著;王张宜等译. 密码编码学与网络安全——原理与实践(第五版)[M]. 北京:电子工业出版社,2012.1.

[2] Daemen J, Rijmen V. AES proposal: Rijndael[J]. 1998.

[3] Advanced Encryption Standard, https://en.wikipedia.org/wiki/Advanced_Encryption_Standard, 2017年3月获取.

[4] Joan Daemen and Vincent Rijmen, The Design of Rijndael, AES - The Advanced Encryption Standard, Springer-Verlag 2002 (238 pp.)

[5] SSE, SSE2, AVX, AVX512等, https://software.intel.com/sites/landingpage/IntrinsicsGuide/, 2017年6月获取.

[6] Libsodium, https://github.com/jedisct1/libsodium, 2017年6月获取.

[7] FastMemcpy, https://github.com/skywind3000/FastMemcpy, 2017年6月获取.

[8] Hamming_weight, https://github.com/CountOnes/hamming_weight, 2017年6月获取.

[9] AES-NI, https://en.wikipedia.org/wiki/AES_instruction_set, 2017年6月获取.

[10] SIMD, https://en.wikipedia.org/wiki/SIMD, 2017年6月获取.

更新说明

2017.11.19

    a) 完善了评选指标的说明;

2017.06.03

    a) 列混淆中加法是模28,不是模2;

    b) 增长了SIMD和AES-NI的介绍;

2017.03.15

    a) 增长了Rijndael和AES的区别;b) 增长了参考文献;c) 提到AES查表的实现;d) 循环移位不以字节为单位,统一改为比特;

    e) 修复了Rijndael算法连接的错误;f) 更正了错别字;

相关文章
相关标签/搜索