AES简介

1、高级加密标准(AES,Advanced Encryption Standard)作为传统对称加密标准DES的替代者,美国国家标准与技术研究所(NIST)于1997年提出征集该算法的公告。
2、1999年3月22日,NIST从15个候选算法中选出 5个算法进入下一轮。在2000年10月2日,以
安全性、性能、大小、实现特点等标准而最
终选定由比利时人的开发的Rijndael算法,
并于2001年正式发布AES标准。

流程图

AES的基本结构(准备阶段)

  • 典型的SPN(代换–置换网络)结构
  • AES又是分组密码,具体过程:将明文分为长度相等的组 (长度固定为128位,即每组16字节),每组逐次加密直到加密完整个明文。
  • 密钥长度位下列三种:
  • AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为:

P=P0P1…P15
K=K0K1…K15

  1. 明文分组用以字节为单位的正方形矩阵描述,称为状态矩阵。(规则:矩阵中字节的排列为从上到下、从左到右依次排 列,矩阵的每一列被称为1个32比特字

整体流程

密钥扩充(加密前奏)

将密钥扩充,需要得到四十个新列,分组得到轮密钥。

CASE1:当W[i]中i为4的整数倍时,需要用T函数进行变换W[i-1],然后用W[i-1]与W[i-4]进行异或,最后得出W[i]
(Ps:T函数由3部分组成:字循环、字节代换和轮常量异或,这三个过程时T函数变换的充分必要条件)
CASE2:当
W[i]中i不是4的整数倍时,只需要将W[i-1]与W[i-4]进行异或,最后得出W[i]
重复相同的流程所处所有的W

核心流程

轮函数示意图

  • 字节代换(SubBytes 非线性)
    定义了S盒:(S盒是由16*16的字节组成的矩阵,S盒不可逆)

    我们通过S盒将明文分组中的元素逐个进行替换。
    例如: 明文分组为:

    第一个元素19,在S盒中寻找第1行第9列的元素即可,按照上述S盒找出为 2D 。

  • 行移位 (ShiftRows 线性)为密码系统提供了扩展性
    是一个简单的左循环位移操作。
    规则 : 第n行就位移n字节
    例如:
    位移前

    位移后

  • 列混合 (MixColumns 非线性)为密码系统提供了扩展性
    简单的矩阵相乘操作
    将以下状态矩阵按列与固定矩阵相乘


    得到相乘的结果换到原来的列位置上

    然后逐列依次进行

  • 轮密钥加
    我们将密钥扩展得到的轮密钥与我们的明文分组矩阵进行逐列的异或操作,将得到结果替换

    替换之后

    之后便进行流程的循环,不同的AES-n位循环的次数都不同,最终得到密文

  • 所有轮数的流程图

AES算法的实现

密钥扩展

//密钥对应的扩展数组
static int w[44];/*** 扩展密钥,结果是把w[44]中的每个元素初始化*/
static void extendKey(char *key) {for(int i = 0; i < 4; i++)w[i] = getWordFromStr(key + i * 4); for(int i = 4, j = 0; i < 44; i++) {if( i % 4 == 0) {w[i] = w[i - 4] ^ T(w[i - 1], j); j++;//下一轮}else {w[i] = w[i - 4] ^ w[i - 1]; }}   }/*** 常量轮值表*/
static const int Rcon[10] = { 0x01000000, 0x02000000,0x04000000, 0x08000000,0x10000000, 0x20000000,0x40000000, 0x80000000,0x1b000000, 0x36000000 };
/*** 密钥扩展中的T函数*/
static int T(int num, int round) {int numArray[4];splitIntToArray(num, numArray);leftLoop4int(numArray, 1);//字循环//字节代换for(int i = 0; i < 4; i++)numArray[i] = getNumFromSBox(numArray[i]);int result = mergeArrayToInt(numArray);return result ^ Rcon[round];
}

字节代换

/*** 根据索引,从S盒中获得元素*/
static int getNumFromSBox(int index) {int row = getLeft4Bit(index);int col = getRight4Bit(index);return S[row][col];
}/*** 字节代换*/
static void subBytes(int array[4][4]){for(int i = 0; i < 4; i++)for(int j = 0; j < 4; j++)array[i][j] = getNumFromSBox(array[i][j]);
}

行位移

/*** 将数组中的元素循环左移step位*/
static void leftLoop4int(int array[4], int step) {int temp[4];for(int i = 0; i < 4; i++)temp[i] = array[i];int index = step % 4 == 0 ? 0 : step % 4;for(int i = 0; i < 4; i++){array[i] = temp[index];index++;index = index % 4;}
}/*** 行移位*/
static void shiftRows(int array[4][4]) {int rowTwo[4], rowThree[4], rowFour[4];//复制状态矩阵的第2,3,4行for(int i = 0; i < 4; i++) {rowTwo[i] = array[1][i];rowThree[i] = array[2][i];rowFour[i] = array[3][i];}//循环左移相应的位数leftLoop4int(rowTwo, 1);leftLoop4int(rowThree, 2);leftLoop4int(rowFour, 3);//把左移后的行复制回状态矩阵中for(int i = 0; i < 4; i++) {array[1][i] = rowTwo[i];array[2][i] = rowThree[i];array[3][i] = rowFour[i];}
}

列混合

/*** 列混合要用到的矩阵*/
static const int colM[4][4] = { 2, 3, 1, 1,1, 2, 3, 1,1, 1, 2, 3,3, 1, 1, 2 };static int GFMul2(int s) {int result = s << 1;int a7 = result & 0x00000100;if(a7 != 0) {result = result & 0x000000ff;result = result ^ 0x1b;}return result;
}static int GFMul3(int s) {return GFMul2(s) ^ s;
}/*** GF上的二元运算*/
static int GFMul(int n, int s) {int result;if(n == 1)result = s;else if(n == 2)result = GFMul2(s);else if(n == 3)result = GFMul3(s);else if(n == 0x9)result = GFMul9(s);else if(n == 0xb)//11result = GFMul11(s);else if(n == 0xd)//13result = GFMul13(s);else if(n == 0xe)//14result = GFMul14(s);return result;
}/*** 列混合*/
static void mixColumns(int array[4][4]) {int tempArray[4][4];for(int i = 0; i < 4; i++)for(int j = 0; j < 4; j++)tempArray[i][j] = array[i][j];for(int i = 0; i < 4; i++)for(int j = 0; j < 4; j++){array[i][j] = GFMul(colM[i][0],tempArray[0][j]) ^ GFMul(colM[i][1],tempArray[1][j])^ GFMul(colM[i][2],tempArray[2][j]) ^ GFMul(colM[i][3], tempArray[3][j]);}
}

轮密钥加

/*** 轮密钥加*/
static void addRoundKey(int array[4][4], int round) {int warray[4];for(int i = 0; i < 4; i++) {splitIntToArray(w[ round * 4 + i], warray);for(int j = 0; j < 4; j++) {array[j][i] = array[j][i] ^ warray[j];}}
}

AES加密函数

/*** 参数 p: 明文的字符串数组。* 参数 plen: 明文的长度。* 参数 key: 密钥的字符串数组。*/
void aes(char *p, int plen, char *key){int keylen = strlen(key);if(plen == 0 || plen % 16 != 0) {printf("明文字符长度必须为16的倍数!\n");exit(0);}if(!checkKeyLen(keylen)) {printf("密钥字符长度错误!长度必须为16、24和32。当前长度为%d\n",keylen);exit(0);}extendKey(key);//扩展密钥int pArray[4][4];for(int k = 0; k < plen; k += 16) {convertToIntArray(p + k, pArray);addRoundKey(pArray, 0);//一开始的轮密钥加for(int i = 1; i < 10; i++){//前9轮subBytes(pArray);//字节代换shiftRows(pArray);//行移位mixColumns(pArray);//列混合addRoundKey(pArray, i);}//第10轮subBytes(pArray);//字节代换shiftRows(pArray);//行移位addRoundKey(pArray, 10);convertArrayToStr(pArray, p + k);}
}

AES解密函数

/*** 参数 c: 密文的字符串数组。* 参数 clen: 密文的长度。* 参数 key: 密钥的字符串数组。*/
void deAes(char *c, int clen, char *key) {int keylen = strlen(key);if(clen == 0 || clen % 16 != 0) {printf("密文字符长度必须为16的倍数!现在的长度为%d\n",clen);exit(0);}if(!checkKeyLen(keylen)) {printf("密钥字符长度错误!长度必须为16、24和32。当前长度为%d\n",keylen);exit(0);}extendKey(key);//扩展密钥int cArray[4][4];for(int k = 0; k < clen; k += 16) {convertToIntArray(c + k, cArray);addRoundKey(cArray, 10);int wArray[4][4];for(int i = 9; i >= 1; i--) {deSubBytes(cArray);deShiftRows(cArray);deMixColumns(cArray);getArrayFrom4W(i, wArray);deMixColumns(wArray);addRoundTowArray(cArray, wArray);}deSubBytes(cArray);deShiftRows(cArray);addRoundKey(cArray, 0);convertArrayToStr(cArray, c + k);}
}

AES算法实现、代码相关推荐

  1. 关于AES算法及JAVA中的实现

    为什么80%的码农都做不了架构师?>>>    什么是AES 密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法, ...

  2. Delphi与JAVA互加解密AES算法

    搞了半天终于把这个对应的参数搞上了,话不多说,先干上代码: package com.bss.util;import java.io.UnsupportedEncodingException; impo ...

  3. aes key长度_AES加密(1): 基本AES算法

    简介 AES原本指的是一套标准FIPS 197,而AES算法一般指分组大小为128bits的Rijndeal算法,由比利时学者Joan Daemen和Vincent Rijmen提出. AES与Rij ...

  4. java aes 模式_Java实现多种加密模式的AES算法-总有一种你用的着!

    前言 对于AES算法,相信很多程序员小伙伴都听过.用过,其原理本文就不介绍了,而是讲讲在实际项目中的应用.前几天,项目需要跟乙方接口对接,乙方提供加密后的信息串,而我这边负责对加密串进行解密.其中加解 ...

  5. aes ios php,AES算法在PHP和Android和iOS上有所不同

    嗨我目前正在使用PHP和Android中的AES算法对字符串进行加密和解密.我在iOS和Android中获得了类似的值.但我无法在PHP中获得相同的输出.它显示了一些其他加密字符串.我想在所有iOS, ...

  6. Android直播开发之旅(25):使用AES算法加密多媒体文件(+RSA+MD5+Base64)

    文章目录 1. AES算法 1.1 AES加密过程 1.1.1 字节代替(SubBytes) 1.1.2 行移位(ShiftRows) 1.1.3 列混合(MixColumns) 1.1.4 加轮密钥 ...

  7. AES算法描述及C语言实现

    前言 AES算法是当前最流行的对称加密算法,也是一种分组加密算法,分组密码就是把明文分为固定长度的一组一组,每次加密一组数据,直到加密完整个明文数据.AES算法根据分组长度可以分为AES128, AE ...

  8. AES算法加解密及简单图像化界面实现

    RIJNDAEL 加密算法 注意:本文实现的AES算法的密钥,明文,密文均为128位,后续可能会添加192位或256位的密钥.函数flag参数默认是1,即加密,在解密调用时改为0即可. 先放个运行效果 ...

  9. [JAVA实战篇] AES加密的JAVA实现及AES算法讲解

    AES加密算法原理 1. S-P结构加密 AES加密算法是2001年由美国提出的互联网加密算法,从密码学的角度来讲,AES是典型的S-P结构加密.什么是S-P结构加密呢,手残博主画了一张图帮助大家理解 ...

  10. 常用对称加密算法之AES算法-CBC模式

    这个需求很简单就是存储数据库密码,因为链接数据库的需要用到,加密就必须要用对称加密算法,于是简单调研了一下对称加密算法,经过对比最后选择了AES算法-CBC模式 怎么理解对称加密 加密:接收秘钥key ...

最新文章

  1. 特斯拉再裁员3000多人,马斯克称别无选择
  2. HBase学习之路 (九)HBase phoenix的使用
  3. 【并发编程】线程池--Executor框架
  4. torch维度获取数据详解
  5. mui实现手机web拍照_WEB前端开发与后端开发比较
  6. 样式图片_中式门窗花格图片大全样式全面选择多
  7. 1644E. Expand the Path
  8. keras手写数字识别--入门
  9. android gif转jpg格式文件,android使用多张图片合成gif文件
  10. php表单密码由加密变明文,PHP 安全性漫谈 Linux+Apache+Mysql+PHP
  11. Java基础之写文件——通过缓冲流写文件(StreamOutputToFile)
  12. 使用ILSpy软件反编译.Net应用程序的方法及注意事项
  13. Firefox 将添加画中画功能
  14. 多模模块接单模光纤跳线/单模模块接多模光纤跳线
  15. 计算机专业和机械自动化哪个好,自动化和机械设计制造及其自动化有哪些区别?选哪个好呢?...
  16. 上市公司环境信息披露合集-上市公司环保补助金额、环保税等三大维度指标(2003-2020年)
  17. “另类”计算IP地址和子网划分
  18. 表格的属性、表格的合并及表单
  19. Linux 并发与竞争
  20. 最高效寻找重复数据,如何高效率的查找到数组中的重复值

热门文章

  1. QT编程:QT int和float转QString
  2. 速看!TIOBE12月编程语言排行榜,第一名太牛啦!
  3. linux ubuntu之lftp的使用
  4. 大话西游 经典台词 翻译
  5. 卷积神经网络结构发展整理(全)
  6. 2022 年全国职业院校技能大赛 网络搭建与应用赛项正式赛卷
  7. 图像blood4.tif是一个血细胞图,图像质量较低,请综合应用图像处理的方法,对图像中的红细胞(大而圆的细胞)进行计数(matlab)
  8. android引导页自动轮播,Android使用ViewPager实现自动轮播
  9. comodo泛域名证书与comodo多域名证书选择
  10. Git版本管理软件使用