当前位置: 首页 > news >正文

AES加密/解密算法

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

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:最后一个字节是填充的字节数(包括最后一字节),其他全部填随机数

3、加密方式

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

ECB:将明文按16字节分组,每组分别加密后拼接。

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

一般采用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                    
******************************************************************************//************************************************************************************************************************************************************/
extern void AES_Init(const void *pKey);/************************************************************************************************************************************************************/
void AES_Encrypt(const unsigned char *pPlainText, unsigned char *pCipherText,unsigned int nDataLen, const unsigned char *pIV);/************************************************************************************************************************************************************/
void AES_Decrypt(unsigned char *pPlainText, const unsigned char *pCipherText,unsigned int nDataLen, const unsigned char *pIV);/**********************************************************************************************************************************************************/
unsigned int AES_add_pkcs7Padding(unsigned char *input, unsigned int len);/**********************************************************************************************************************************************************/
unsigned int AES_delete_pkcs7Padding(unsigned char *input, unsigned int len);
#endif  /* _AES_H
/****************************************************************************
*  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, 0x10, 0xff, 0xf3, 0xd2,0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};// 解密用的SBox
static const unsigned char InvSBox[256] =
{0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};/*****************************************************************************
*  Local Functions
******************************************************************************//**********************************************************************************************************************************************************/
static void RotationWord(unsigned char *pWord)
{unsigned char temp = pWord[0];pWord[0]  = pWord[1];pWord[1]  = pWord[2];pWord[2]  = pWord[3];pWord[3]  = temp;
}/**********************************************************************************************************************************************************/
static void XorBytes(unsigned char *pData1, const unsigned char *pData2, unsigned char nCount)
{unsigned char i;for(i = 0; i < nCount; i++){pData1[i] ^= pData2[i];}
}/**********************************************************************************************************************************************************/
static void AddRoundKey(unsigned char *pState, const unsigned char *pRoundKey)
{XorBytes(pState, pRoundKey, 4 * Nb);
}// AddRoundKey的宏形式,比函数形式可以节省4字节的data数据
//#define AddRoundKey(pState, pRoundKey) \
// XorBytes((pState), (pRoundKey), 4*Nb)/**********************************************************************************************************************************************************/
static void SubBytes(unsigned char *pState, unsigned char nCount, unsigned char bInvert)
{unsigned char i;const unsigned char *pSBox = bInvert ? InvSBox : SBox;for(i = 0; i < nCount; i++){pState[i] = pSBox[pState[i]];}
}/**********************************************************************************************************************************************************/
static void ShiftRows(unsigned char *pState, unsigned char bInvert)
{// 注意:状态数据以列形式存放!unsigned char r; // row,   行unsigned char c; // column,列unsigned char temp;unsigned char rowData[4];for(r = 1; r < 4; r++){// 备份一行数据for(c = 0; c < 4; c++){rowData[c] = pState[r + 4*c];}temp = bInvert ? (4 - r) : r;for(c = 0; c < 4; c++){pState[r + 4*c] = rowData[(c + temp) % 4];}}
}/**********************************************************************************************************************************************************/
static unsigned char GfMultBy02(unsigned char num)
{if((num & 0x80) == 0){num = num << 1;}else{num = (num << 1) ^ BPOLY;}return num;
}/**********************************************************************************************************************************************************/
static void MixColumns(unsigned char *pState, unsigned char bInvert)
{unsigned char i;unsigned char temp;unsigned char a0Pa2_M4; // 4(a0 + a2)unsigned char a1Pa3_M4; // 4(a1 + a3)unsigned char result[4];for(i = 0; i < 4; i++, pState += 4){temp = pState[0] ^ pState[1] ^ pState[2] ^ pState[3];result[0] = temp ^ pState[0] ^ GfMultBy02((unsigned char)(pState[0] ^ pState[1]));result[1] = temp ^ pState[1] ^ GfMultBy02((unsigned char)(pState[1] ^ pState[2]));result[2] = temp ^ pState[2] ^ GfMultBy02((unsigned char)(pState[2] ^ pState[3]));result[3] = temp ^ pState[3] ^ GfMultBy02((unsigned char)(pState[3] ^ pState[0]));if(bInvert){a0Pa2_M4 = GfMultBy02(GfMultBy02((unsigned char)(pState[0] ^ pState[2])));a1Pa3_M4 = GfMultBy02(GfMultBy02((unsigned char)(pState[1] ^ pState[3])));temp  = GfMultBy02((unsigned char)(a0Pa2_M4 ^ a1Pa3_M4));result[0] ^= temp ^ a0Pa2_M4;result[1] ^= temp ^ a1Pa3_M4;result[2] ^= temp ^ a0Pa2_M4;result[3] ^= temp ^ a1Pa3_M4;}memcpy(pState, result, 4);}
}/**********************************************************************************************************************************************************/
static void BlockEncrypt(unsigned char *pState)
{unsigned char i;AddRoundKey(pState, g_roundKeyTable);for(i = 1; i <= Nr; i++) // i = [1, Nr]{SubBytes(pState, 4 * Nb, 0);ShiftRows(pState, 0);if(i != Nr){MixColumns(pState, 0);}AddRoundKey(pState, &g_roundKeyTable[4*Nb*i]);}
}/**********************************************************************************************************************************************************/
static void BlockDecrypt(unsigned char *pState)
{unsigned char i;AddRoundKey(pState, &g_roundKeyTable[4*Nb*Nr]);for(i = Nr; i > 0; i--) // i = [Nr, 1]{ShiftRows(pState, 1);SubBytes(pState, 4 * Nb, 1);AddRoundKey(pState, &g_roundKeyTable[4*Nb*(i-1)]);if(i != 1){MixColumns(pState, 1);}}
}/*****************************************************************************
*  Global Functions
******************************************************************************//**********************************************************************************************************************************************************/
void AES_Init(const void *pKey)
{// 扩展密钥unsigned char i;unsigned char *pRoundKey;unsigned char Rcon[4] = {0x01, 0x00, 0x00, 0x00};memcpy(g_roundKeyTable, pKey, 4 * Nk);pRoundKey = &g_roundKeyTable[4*Nk];for(i = Nk; i < Nb*(Nr + 1); pRoundKey += 4, i++){memcpy(pRoundKey, pRoundKey - 4, 4);if(i % Nk == 0){RotationWord(pRoundKey);SubBytes(pRoundKey, 4, 0);XorBytes(pRoundKey, Rcon, 4);Rcon[0] = GfMultBy02(Rcon[0]);}else if(Nk > 6 && i % Nk == Nb){SubBytes(pRoundKey, 4, 0);}XorBytes(pRoundKey, pRoundKey - 4 * Nk, 4);}
}/**********************************************************************************************************************************************************/
void AES_Encrypt(const unsigned char *pPlainText, unsigned char *pCipherText,unsigned int nDataLen, const unsigned char *pIV)
{unsigned int i;if(pPlainText != pCipherText){memcpy(pCipherText, pPlainText, nDataLen);}for(i = nDataLen / (4 * Nb); i > 0 ; i--, pCipherText += 4 * Nb){
#if AES_MODE == AES_MODE_CBCXorBytes(pCipherText, pIV, 4 * Nb);
#endifBlockEncrypt(pCipherText);pIV = pCipherText;}
}/**********************************************************************************************************************************************************/
void AES_Decrypt(unsigned char *pPlainText, const unsigned char *pCipherText,unsigned int nDataLen, const unsigned char *pIV)
{unsigned int i;if(pPlainText != pCipherText){memcpy(pPlainText, pCipherText, nDataLen);}// 从最后一块数据开始解密,这样不用开辟空间来保存IVpPlainText += nDataLen - 4 * Nb;for(i = nDataLen / (4 * Nb); i > 0 ; i--, pPlainText -= 4 * Nb){BlockDecrypt(pPlainText);#if AES_MODE == AES_MODE_CBCif(i == 1){// 最后一块数据XorBytes(pPlainText, pIV, 4 * Nb);}else{XorBytes(pPlainText, pPlainText - 4 * Nb, 4 * Nb);}
#endif}
}/**********************************************************************************************************************************************************/
unsigned int AES_add_pkcs7Padding(unsigned char *input, unsigned int len)
{unsigned int i, end, padd_len;unsigned int reminder = len % 16;unsigned int block = len / 16;unsigned int start = len;//开始补码的地址padd_len = len;if(reminder != 0) //需要补足为16的整数倍{start = len;end = (block + 1) * 16;for(i = start; i < end; i++){input[i] = 16 - reminder;padd_len++;}}else{end = start + 16;for(i = start; i < end; i++){input[i] = 16;padd_len++;}}return padd_len;
}/**********************************************************************************************************************************************************/
unsigned int AES_delete_pkcs7Padding(unsigned char *input, unsigned int len)
{unsigned char i, last;if((input == 0) || ((len & 0x0F) != 0)){return 0;}last = input[len - 1];for(i = len - last; i < len; i++){if(input[i] != last){return 0;}}return len - last;
}
#include "aes.h"
#include "stdio.h"
#include "string.h"void log(char *head,unsigned char *data,unsigned char len)
{unsigned char i;printf("%s:",head);for(i=0;i<len;i++){printf("%02X ",data[i]);}printf("\r\n");
}int main(int argc, char *argv[])
{//秘钥unsigned char key[16]={0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x41,0x42,0x43,0x44,0x45,0x46};//明文 10Bytesunsigned char source[10]={0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30};unsigned char temp[16]={0};unsigned char ret;printf("AES-128 pkcs7 ECB test\r\n\r\n");log("KEY   ",key,16);AES_Init(key);memcpy(temp,source,10);log("source",key,10);ret=AES_add_pkcs7Padding(temp, 10);log("padd  ",temp,ret);AES_Encrypt(temp, temp,ret, NULL);log("encode",temp,ret);AES_Decrypt(temp, temp,ret, NULL);log("decode",temp,ret);ret=AES_delete_pkcs7Padding(temp, ret);log("source",temp,ret);return 0;
}

http://www.dtcms.com/a/412446.html

相关文章:

  • 用网站做微信公众号台州做网站seo
  • 如何让网站互动起来ts431p 做网站
  • 土石方工程网站系统开发流程8个步骤
  • MRIcron画大脑叠加图
  • 自己做的网站能放到网上么开发网站用php还是jsp
  • 如何自己建个网站中国建筑公司排名最新五十强
  • ps可以做网站动态图做网站欢迎页什么意思
  • 用drupal做的网站百度权重高的网站
  • 长春 万网 网站建设哈尔滨免费模板建站
  • 织梦网站地图在线生成网建会是什么意思
  • 做hmtl的基本网站调用wordpress媒体库
  • RAG技术全面指南:解锁大模型应用的未来
  • AppGallery Connect(HarmonyOS 5及以上) --公开测试创建并发布测试版本(一)
  • 网站研发费用吗WordPress新版文章标签
  • 网站公司动态做不了怎么办做网站月度总结
  • 网站页面小图标怎么做wordpress点赞功能
  • 湖南(源点咨询)市场调研如何在行业研究中快速有效介入 补充篇
  • 开学季“心”准备|心理普测怎么做?朗心心理信息化管理平台筑牢校园心理安全防线
  • 广东泰通建设有限公司网站东莞seo建站广告费
  • 医药医疗行业网站建设去水印小程序源码
  • # 打工人日报#20250926
  • MODBUS 协议详细解读
  • Unity避坑——继承了MonoBehaviour的对象不能通过new来创建
  • 网站和网页wordpress修改邮件模板
  • 必应网站建设开源企业网站源码
  • 官方网站的资料做证据百度seo优化招聘
  • VSCode+MSVC+Qmake环境搭建笔记
  • 公司做网站选择哪个公司好数据库网站建设教程
  • 430亿美元押注英国,Salesforce 加码 AI 投资
  • 「React实战面试题」:状态批量更新的经典陷阱