AES 基本运算

 
1. AES基本运算
为了简化运算,接下来介绍的算法都是基于这样的假设:
a) 算法密钥为128位,每个块为128位,也就是16个字节。
b) 每种变换算法的输入都是一个块,也就是每次处理16个字节
AES加密过程由4个基本基本动作组成,包括:S盒变换、行移位变化、列混合变换、轮密钥加法变换。接下来,我们看看这些细节是如何实现的。
1) S盒变换
算法:通过查表SBox实现。以16个字节为基本单位,分别对每个字节查表替换以相应的表中内容。
void SubBytes(BYTE state[16])
{
for(int i=0; i<16;i++)
{
state[i] = SBox[state[i]];
}
return;
}
SBox可以通过计算生成。也可以以全局数组的形式直接写入代码中。
以下方法用来计算SBox[x]
BYTE c= 0×63;
求字节x的逆:b = GF_Reverse(x)
然后,依次计算每一位
for i=0 to 7
//bit(b,i)返回字节b的第i位的值:0或1。⊕为异或预算
B= bit(b, i) ⊕bit(b, (i+4)mod8) ⊕ bit(b, (i+5) mod8)
⊕ bit(b, (i+6)mod8) ⊕bit(b, (i+7)mod8) ⊕ bit(c, i)
setbit(SBox[x], i, B) //设置SBox[x]的第i位为B
endfor
2) 行移位变换
这个变换很简单:输入为state[16]。state[0]-state[3]不变,state[4]-state[7]循环左移1个字节,state[8]-state[11] 循环左移2个字节,state[12]-state[15] 循环左移3个字节
算法如下:
输入:16个字节构成的一个块state[16]
输出:变换后的结果保存在state[16]
Void ShiftRows( BYTE state[16])
{
BYTE t[4];
for(int i=1; i<4; i++)
{
for( int j=0; j<4; j++ )
{
t[j] = state[ i*4 + (j+i)%4 ];
}
memcpy(state+4*i, t, 4);
}
}
3) 列混合变换
输入:16个字节构成的一个块:state[16]
输出:变换后的结果保存在state[16]
算法:按列处理,每列表示为s(x) = S[3][i]x3+ S[2][i]x2+ S[1][i]x+ S[0][i],然后计算
[{03}x3+{01}x2+{01}X+{02}]*s(x) mod (x4+1) 得到新的多项式,其系数对应S[0][i]-S[3][i]变换后的字节值。
代码如下:
Void MixColumns(BYTE state[16])
{
BYTE temp[4][4];
memcpy(temp, state, 16); //将state复制到temp中,temp[i][j]=state[i*4+j]
for(int i=0; i<4; i++) //第i列
{
for(int j=0; j<4; j++) //第j行,⊕为异或运算
{
state[j*4+i] =
GF_Mul(0×2, temp[j][i])
⊕GF_ Mul (0×3, temp[(j+1) mod 4][i])
⊕temp[ (j+2)mod 4 ][i] ⊕temp[ (j+3)mod 4 ][i] ;
}
}
}
4) 轮密钥加法变换
每个块的加密都要经过Nr(不妨取Nr=10)轮变换。在第i轮变换,使用第i个扩展密钥k(i)
变换是输入与密钥异或的过程
代码如下:
void AddRoundKey(BYTE state[16],BYTE key[16])
{
for(int i=0; i<4; i++)
{
for( int j=0; j<4; j++ )
{
state[ i*4 + j] = state[ i*4 + j] ⊕key[j*4+i];
}
}
}
5) 密钥扩展算法
选取128位的密钥,也就是16个字节的密钥,通过扩展算法,生成Nr个扩展密钥。
对于第r轮(r从1开始计数)用的密钥
输入: r表示当前要扩展第r轮密钥,r>0
数组key的前16字节放入第r-1轮密钥
输出: 数组key的后16字节写入第r轮密钥
注意: 第0轮的密钥也就是初始密钥
void make_key(BYTE key[32], int r)
{
const BYTE RC[10]={0×1,0×2,0×4,0×8,0×10,0×20,0×40,0×80,0×1B,0×36};
BYTE *temp = key;
DWORD *dw_key= (( DWORD*)(temp));
//存储第四个双字,也就是最后4个字节
DWORD dw3= dw_key[3];
//对第一个字,旋转并替换
BYTE t = temp[4*3+0];
temp[4*3+0] = gSBox[temp[4*3+1]];
temp[4*3+1] = gSBox[temp[4*3+2]];
temp[4*3+2] = gSBox[temp[4*3+3]];
temp[4*3+3] = gSBox[t];
//对第一个字,异或
temp[4*3] = temp[4*3]^RC[r-1];
//第i-1个字 与 第i-3个字
for(int i=4; i<7;i++)
{
dw_key[i] = dw_key[i-1]^dw_key[i-4];
}
dw_key[7] = dw_key[6]^dw3;
dw_key[3] = dw3;
}
通过反复调用函数make_key就可以生成任意轮扩展密钥。对于128位的密钥,可以取Nr=10。
本文来源于Sino Blog http://www.sinoblog.org , 原文地址: http://www.sinoblog.org/2008/04/193.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值