AES加密算法及其具体步骤笔记

AES 高级加密标准

前言

之前一直想写CSDN博客但是没有找到可以写的内容,趁着最近刚好在学密码学就可以把自己学习时候的笔记贴上来啦。因为比较菜…所以内容几乎都是参考了教材、百度和wiki里面的,自己整理重述了一下~

AES背景

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。

该算法为比利时密码学家Joan DaemenVincent Rijmen所设计,结合两位作者的名字,以Rijndael为名投稿高级加密标准的甄选流程。(Rijndael的发音近于"Rhine doll")

算法描述

在原始的Rijndael算法中分组长度和密钥长度都可变,各自可以独立的指定为128 bit、192 bit、256 bit。在AES中,分组长度只能是128 bit,也就是16个字节。(1个字节等于8位,1 Byte = 8 Bit)。密钥长度可以为三者中的任意一种。最广泛 的使用是密钥128 bit,迭代轮数10轮。

AES算法密钥长度(32 bit)分组长度(32 bit)加密和解密轮数
AES-1284410
AES-1926412
AES-2568414

对称密钥使用相同的密钥进行加密和解密,因此发送者和接受者都必须知道并使用相同的秘密密钥。
本文主要基于AES-128。

算法流程图

这个流程图是在github上看到的,自己画的有点简陋,这个图非常清晰就拿来了2333
(后面有几张图好像也是,我把原链接贴在这里)
图源 link
在这里插入图片描述
自己重新整理了一下画的流程图大概长这样:

Round Function
9 times
Final Round
PlainText
AddRoundKey
Key
KeyExpansion
SubBytes
ShiftRows
MixColumns
AddRoundKey
SubBytes
ShiftRows
AddRoundKey
CipherText

下面就详细的讲一些流程图里面的每一个部分

State Matrix

Block cipher is a cryptosystem which encrypts data not by bit but by block,which is group of bits,applying algorithm per block.

分组密码不是按位对数据进行加密,而是按每一组对数据进行整体加密算法。所以首先对明文、密钥进行分组,每一组为1 byte(8 bit),16 x 8=128 bit,因此一共分成了16组,用 4 x 4矩阵表示,该矩阵就称为状态矩阵(State Matrix)。对应上图AddRoundKeyKey Expansion上方的矩阵。
state matrix
用C++实现如下:

//将明文分组拷贝到状态矩阵中
unsigned char state[16];
for (int i = 0; i < 16; i++)
{
	state[i] = message[i];
}

Key Expansion

Key Expansion是将用户输入的key扩展生成多组轮密钥。对应AES-128,AES-192,AES-256,分别扩展出11,13,15组。

假设我们所用的加密方法为AES-128标准,则需要将4个字(1 word = 32 bit)的原始密钥扩展成44个字的轮密钥(4 x 11轮)。具体步骤如下图所示:
图源link
在这里插入图片描述

g函数

g函数是一个复杂函数,由三个步骤构成:字循环,字节代换和轮常量异或。

  1. 字循环

    将1个字的4个字节循环左移1个字节,即将字[b0,b1,b2,b3]变为[b1,b2,b3,b0]。

  2. 字节代换

    基于S盒对输入字中的每个字节进行S代替。

  3. 轮常量异或

    轮常量Rcon[i]数据表如下:
    在这里插入图片描述

eg: 假如第8回合的回合密钥为:

EA D2 73 21 B5 8D BA D2 31 2B F5 60 7F 8D 29 2F

那么,第9回合密钥的前4个字节(第一列)的计算过程如下:

temp字循环字节代换Rcon[9]XOR Rconw[i-4]w[i]
7F8D292F8D292F7F5DA515D21B00000046A515D2EZD27321AC7766F3
  • temp存第8回合密钥的最后一个字(最后一列)

  • 字循环和字节代换都是对temp数组里的数据

  • Rcon[9]由上图数据表得出

  • XOR Rcon是将temp与Rcon[9]异或

    此时完成了上图中w到w的步骤

  • w[i-4]是第8回合密钥的第1个字(第一列)

  • w[i]为最后结果,w[i]=w XOR w[i-4]

AddRoundKey

Add round key其实就是将128位的密钥和128位的明文进行逐位异或操作。
在这里插入图片描述
用C++实现如下

void AddRoundKey(state, roundkey)
{
	//roundkey 和 state XOR!
	for (int i = 0; i < 16; i++)
	{
		state[i] ^= roundkey[i];
	}
}

Round Function

1. SubBytes

将字节代换的各种可能字节的变换结果排成一个表,称为AES的字节代替表或者S盒。状态矩阵中的元素按照下面的方式通过S盒映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒对应行列的元素作为输出。例如,加密时输入字节 0x12,则查找S盒的第 0x01行,0x02 列,得到的值为 0xC9。S盒如下:
在这里插入图片描述
用C++实现如下:

void SubBytes(unsigned char* state)
{
	//S盒字节替换
	for (int i = 0; i < 16; i++)
	{
		state[i] = s_box[state[i]];
	}
}
2. ShiftRows

行位移是将状态矩阵的各行进行循环移位,不同状态行的位移量不同。第0行不移动,第1行循环左移1个字节,第2行循环左移2个字节,第3行循环左移3个字节。如图所示:
在这里插入图片描述
图源自link

用C++实现如下:

void ShiftRows(unsigned char* state)
{
	unsigned char tmp[16];

	//tmp暂存行位移的结果
	tmp[0] = state[0];
	tmp[1] = state[5];
	tmp[2] = state[10];
	tmp[3] = state[15];

	tmp[4] = state[4];
	tmp[5] = state[9];
	tmp[6] = state[14];
	tmp[7] = state[3];

	tmp[8] = state[8];
	tmp[9] = state[13];
	tmp[10] = state[2];
	tmp[11] = state[7];

	tmp[12] = state[12];
	tmp[13] = state[1];
	tmp[14] = state[6];
	tmp[15] = state[11];

	//行位移
	for (int i = 0; i < 16; i++)
	{
		state[i] = tmp[i];
	}
}
3. MixColumns

列混合是一个替代操作,是AES算法中最复杂的一步,只在第0到r-1轮中用到,最后一轮不使用该变换。是通过将state矩阵与常矩阵C相乘以达到在列上的扩散,实质是在有限域GF(256)上的多项式乘法运算。
在这里插入图片描述其中常矩阵C为:
在这里插入图片描述用C++实现如下:

void MixColumns(unsigned char* state)
{
	unsigned char tmp[16];

	//用临时数组保存
	tmp[0] = (unsigned char)(mul2[state[0]] ^ mul3[state[1]] ^ state[2] ^ state[3]);
	tmp[1] = (unsigned char)(state[0] ^ mul2[state[1]] ^ mul3[state[2]] ^ state[3]);
	tmp[2] = (unsigned char)(state[0] ^ state[1] ^ mul2[state[2]] ^ mul3[state[3]]);
	tmp[3] = (unsigned char)(mul3[state[0]] ^ state[1] ^ state[2] ^ mul2[state[3]]);

	tmp[4] = (unsigned char)(mul2[state[4]] ^ mul3[state[5]] ^ state[6] ^ state[7]);
	tmp[5] = (unsigned char)(state[4] ^ mul2[state[5]] ^ mul3[state[6]] ^ state[7]);
	tmp[6] = (unsigned char)(state[4] ^ state[5] ^ mul2[state[6]] ^ mul3[state[7]]);
	tmp[7] = (unsigned char)(mul3[state[4]] ^ state[5] ^ state[6] ^ mul2[state[7]]);

	tmp[8] = (unsigned char)(mul2[state[8]] ^ mul3[state[9]] ^ state[10] ^ state[11]);
	tmp[9] = (unsigned char)(state[8] ^ mul2[state[9]] ^ mul3[state[10]] ^ state[11]);
	tmp[10] = (unsigned char)(state[8] ^ state[9] ^ mul2[state[10]] ^ mul3[state[11]]);
	tmp[11] = (unsigned char)(mul3[state[8]] ^ state[9] ^ state[10] ^ mul2[state[11]]);

	tmp[12] = (unsigned char)(mul2[state[12]] ^ mul3[state[13]] ^ state[14] ^ state[15]);
	tmp[13] = (unsigned char)(state[12] ^ mul2[state[13]] ^ mul3[state[14]] ^ state[15]);
	tmp[14] = (unsigned char)(state[12] ^ state[13] ^ mul2[state[14]] ^ mul3[state[15]]);
	tmp[15] = (unsigned char)(mul3[state[12]] ^ state[13] ^ state[14] ^ mul2[state[15]]);

	//将数据复制到state
	for (int i = 0; i < 16; i++)
	{
		state[i] = tmp[i];
	}
}
4. Add round key

与初始Add round key一样。

Final Round

由上面流程图可以看出,最后一轮没有MixColumns,其他SubBytes,ShiftRows,AddRoundKey都与上述步骤一样。

内容基本就是这么多了,可能会有错误的地方,如果有任何问题欢迎评论~蟹蟹

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值