AES - Rijndael 算法(一)

1997年1月,美国标准技术协会NIST开始遴选数据加密标准(Data Encryption Standard,简称DES)替代者的工作,称为高级加密标准[1’2](Advanced Eneryption Stand-ard,简称AES)。同年9月便发布了征集算法的正式公告,用,而且要求AES能在全世界范围内免费得。次年6月提交的21个算法中,有15个满足所有的必备条件并被接纳为AEs的候选算法。经过二轮筛选后,1999年8月公布了五个人围的候选算法:IBM公司提供的 MARS算法、RSA开发的RC6算法、剑桥大学和加利弗尼亚圣地亚哥大学等共同提出的Serpent算法以及因特网安全公司、加利弗尼亚伯克利大学、普林斯顿大学等共同开发的Twofish算法和比利时的两位密码学家设计的Rijndael算法。经过第三轮筛选,Rijndael算法因在安全性、实现代价、实现特性等方面都超过其它算法而得胜。

一:Rijndael算法介绍

AES具有128比特的分组长度,三种可选密钥长度:128比特、192比特和256比特。AES是一个迭代型密码, 轮数Nr依赖于密钥长度,当密钥为128比特时,Nr=10; 当密钥为192比特时,Nr=12;当密钥为256比特时,Nr=14。AES的算法描述如下:

  (1)给定一个明文z,将State初始化为x,并进行AddRound—Key操作,将Roundkey与State异或。

  (2)对前Nr一1轮中的每一轮,用S盒对进行一次代换操作,称为SubBytes;对State做一置换ShiftRows;再对State做一次操作MixColumns;然后进行AddRoundKey操作。

  (3)依次进行SubBytes、ShiftRows和AddRoundKey操作。

  (4)将State定义为密文y。

二:Rijndael算法分析

理解AES算法的各种操作是理解AES算法的关键。在AES算法中依次用了AddRoundKey操作、SubBytes操作、ShiftRows操作、MixColumns操作,我们将对这些操作一一进行介绍。

1.AddRoundKey操作
     ***********************************************************
      /* Round key addition function */
 void KeyAdd(u8 state[4][4], u8 roundKeys[11][4][4], int round)
 {
  int i, j;
  for (i=0; i<4; i++)
   for (j=0; j<4; j++)
    state[i][j] ^= roundKeys[round][i][j];
  return;
 }

************************************************************

2.SubBytes操作
     ***********************************************************
     /* Byte substitution transformation */
 int ByteSub(u8 state[4][4])
 {
  int i, j;
  for (i=0; i<4; i++)
   for (j=0; j<4; j++)
    state[i][j] = S[state[i][j]];
  return 0;
 }
     ***********************************************************

3.ShiftRows操作
     ***********************************************************
 /* Row shift transformation */
 void ShiftRow(u8 state[4][4])
 {
  u8 temp;
  /* left rotate row 1 by 1 */
  temp = state[1][0];
  state[1][0] = state[1][1];
  state[1][1] = state[1][2];
  state[1][2] = state[1][3];
  state[1][3] = temp;
  /* left rotate row 2 by 2 */
  temp = state[2][0];
  state[2][0] = state[2][2];
  state[2][2] = temp;
  temp = state[2][1];
  state[2][1] = state[2][3];
  state[2][3] = temp;
  /* left rotate row 3 by 3 */
  temp = state[3][0];
  state[3][0] = state[3][3];
  state[3][3] = state[3][2];
  state[3][2] = state[3][1];
  state[3][1] = temp;
  return;
 }

***********************************************************

4.MixColumns操作
     ***********************************************************
     /* MixColumn transformation*/
 void MixColumn(u8 state[4][4])
 {
  u8 temp, tmp, tmp0;
  int i;
  /* do one column at a time */
  for (i=0; i<4;i++)
  {
   temp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i];
   tmp0 = state[0][i];

/* Xtime array does multiply by x in GF2^8 */
   tmp = Xtime[state[0][i] ^ state[1][i]];
   state[0][i] ^= temp ^ tmp;
   tmp = Xtime[state[1][i] ^ state[2][i]];
   state[1][i] ^= temp ^ tmp;
   tmp = Xtime[state[2][i] ^ state[3][i]];
   state[2][i] ^= temp ^ tmp;
   tmp = Xtime[state[3][i] ^ tmp0];
   state[3][i] ^= temp ^ tmp;
  }
  return;
 }
     ***********************************************************

参考文档:

3GPP TS 35.206

上一篇:常见的几种 CSS 水平垂直居中解决办法


下一篇:SeaJS学习笔记(一) ./ 和 ../ 区别