嵌入式算法6---AES加密/解密算法

需要与外界进行数据交互传输的电子产品,为保证数据安全,一般会对明文进行加密处理。总的来说就是将真正需要传输的内容转换成无法理解的数据,接收方通过预先定义的方式还原,防止第三方截取篡改。比如欧盟对数据隐私有严格的条例GDPR标准。加密算法很多,对于简单的嵌入式产品,使用对称加密算法,即加密和解密使用相同的秘钥,方便快捷。AES就属于这种,虽然存在一定风险,但对于个人消费产品已满足安全需求。
在这里插入图片描述

不考虑算法实现本身,本文只针对应用进行说明。

1、秘钥类型

AES加密按秘钥的长度分为128位(比特)、192位和256位,一般记为AES-128、AES-192和AES-256。一般简短数据采用AES-128,也就是秘钥是16字节,少部分采用AES-256。

2、填充方式

待加密的明文以16字节分组进行加密,如果数据字节长度不是16的倍数,最后的一组则需要在有效数据后面进行填充,使得数据长度变为16字节,AES填充方式分为NoPadding、PKCS5(PKCS7)、ISO10126、Zeros。
NoPadding:不填充,那就只能加密长度为16倍数的数据,一般不使用
Zeros:补0,如果原数据长度恰好是16的倍数,也要补16个0
ISO10126: 最后一个字节是填充的字节数(包括最后一字节),其他全部填随机数

1 2 3 4 5 6 7 8 9 10 – x x x x x 6
填充6个字节

PKCS5(PKCS7):应用比较多,最后一组缺几个字节就填充几

1 2 3 4 5 6 7 8 9 10 – 6 6 6 6 6 6
前面10个字节,缺6字节才能为一组,填充6个6,如果恰好是16个字节,则填充16个16.

3、加密方式

加密方式分为五种:电码本模式(Electronic Codebook Book (ECB))、密码分组链接模式(Cipher Block Chaining (CBC))、计算器模式(Counter (CTR))、密码反馈模式(Cipher FeedBack (CFB))、输出反馈模式(Output FeedBack (OFB))。实际应用比较多的是ECB和CBC。

ECB:将明文按16字节分组,每组分别加密后拼接。
在这里插入图片描述

CBC:上面ECB缺点是明文内相同的明文块,最终的密文也是相同的,为了更好的隐藏明文信息,针对这个问题就有了CBC模式,每一小段明文先与初始块向量或者上一段的密文段进行异或运算后,再与密钥进行加密。
在这里插入图片描述

4、源码

一般采用AES-128,以PKCS7Padding填充,ECB或者CBC方式。针对这种应用参考范例如下。
aes.h

#ifndef _AES_H
#define _AES_H

/****************************************************************************
*  Include Files                       
*****************************************************************************/


/*****************************************************************************
*  Define                              
******************************************************************************/
//以bit为单位的密钥长度,只能为 128,192 和 256 三种
#define AES_KEY_LENGTH	128

//加解密模式
#define AES_MODE_ECB	0				// 电子密码本模式
#define AES_MODE_CBC	1				// 密码分组链接模式
#define AES_MODE		AES_MODE_ECB	// 配置加密模式

/*****************************************************************************
*  Functions Define                    
******************************************************************************/

/******************************************************************************
//	函数名:	AES_Init
//	描述:		初始化,在此执行扩展密钥操作。
//	输入参数:	pKey -- 原始密钥,其长度必须为 AES_KEY_LENGTH/8 字节。
//	输出参数:	无。
//	返回值:	无。
******************************************************************************/
extern void AES_Init(const void *pKey);

/******************************************************************************
//	函数名:	AES_Encrypt
//	描述:		加密数据
//	输入参数:	pPlainText	-- 明文,即需加密的数据,其长度为nDataLen字节。
//				nDataLen	-- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
//				pIV			-- 初始化向量,如果使用ECB模式,可设为NULL。
//	输出参数:	pCipherText	-- 密文,即由明文加密后的数据,可以与pPlainText相同。
//	返回值:	无。
******************************************************************************/
void AES_Encrypt(const unsigned char *pPlainText, unsigned char *pCipherText,
                 unsigned int nDataLen, const unsigned char *pIV);

/******************************************************************************
//	函数名:	AES_Decrypt
//	描述:		解密数据
//	输入参数:	pCipherText -- 密文,即需解密的数据,其长度为nDataLen字节。
//				nDataLen	-- 数据长度,以字节为单位,必须为AES_KEY_LENGTH/8的整倍数。
//				pIV			-- 初始化向量,如果使用ECB模式,可设为NULL。
//	输出参数:	pPlainText  -- 明文,即由密文解密后的数据,可以与pCipherText相同。
//	返回值:	无。
******************************************************************************/
void AES_Decrypt(unsigned char *pPlainText, const unsigned char *pCipherText,
                 unsigned int nDataLen, const unsigned char *pIV);

/*****************************************************************************
//	函数名:	AES_add_pkcs7Padding
//	描述:		PKCS7Padding填充补齐
//	输入参数:	input -- 后面最多预留16个字节空间用于存放填充值
//				len --  数据的长度
//	输出参数:	input  -- 添加填充码后的数据
//	返回值:	填充后的长度
*****************************************************************************/
unsigned int AES_add_pkcs7Padding(unsigned char *input, unsigned int len);

/*****************************************************************************
//	函数名:	AES_delete_pkcs7Padding
//	描述:		PKCS7Padding填充密文解密后剔除填充值
//	输入参数:	input -- 解密后的数据
//				len --  数据的长度
//	输出参数:	input  -- 删除填充码后的数据
//	返回值:	删除后的实际有效数据长度,为0表示传入的数据异常
*****************************************************************************/
unsigned int AES_delete_pkcs7Padding(unsigned char *input, unsigned int len);
#endif  /* _AES_H */

aes.c

/****************************************************************************
*  Include Files
*****************************************************************************/
#include "aes.h"
/*****************************************************************************
*  Define
******************************************************************************/


#define Nk	(AES_KEY_LENGTH / 32)		//以“字”(4字节)为单位的密钥长度
#define Nb	4						// 以“字”(4字节)为单位的加解密数据块大小,固定为4

// Nr:加密的轮数
#if   AES_KEY_LENGTH == 128
#define Nr	10
#elif AES_KEY_LENGTH == 192
#define Nr	12
#elif AES_KEY_LENGTH == 256
#define Nr	14
#else
#error AES_KEY_LENGTH must be 128, 192 or 256
#endif

// GF(28) 多项式
#define BPOLY 0x1B // Lower 8 BOOLs of (x^8 + x^4 + x^3 + x + 1), ie. (x^4 + x^3 + x + 1).


/*****************************************************************************
*  Local variable
*****************************************************************************/

// AES子密钥表,当密钥长度为128位时,占用176字节空间
static unsigned char g_roundKeyTable[4*Nb*(Nr+1)];

// 加密用的SBox
static const unsigned char SBox[256] =
{
   
   
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值