【AES密码编写】

1. Equipment

(1) operating system version :WIN 10

(2) CPU instruction set: x 64

(3) software :Visual Studio 2019

2. process
  • Problem background analysis

AES密码编写

​要编写AES算法,首先了解AES算法原理,AES算法是一个对称分组密码算法。数据分组长度必须是 128 bits,使用的密钥长度为 128,192 或 256 bits。对于三种不同密钥长度的 AES 算法,分别称为“AES-128”、“AES-192”、“AES-256”。AES加密算法涉及4种操作:字节替代(SubBytes)、行移位(ShiftRows)、列混(MixColumns)和轮密钥加(AddRoundKey)。

​ 从AES的加密和解密的流程图中可知:解密算法的每一步分别对应加密算法的逆操作。加解密所有操作的顺序正好是相反的,正是这样才保证了算法的正确性。加解密中每轮的密钥分别由种子密钥经过密钥扩展算法得到,算法中16字节的明文、密文和轮子密钥都以一个4x4的矩阵表示。

AES的加密和解密的流程如下:

​ 按照每一步的具体作用来编写对应的函数,以此实现AES算法过程。

  • Solution

code:

#include <stdio.h>
#pragma warning(disable:4996)
/** @Author:timerring* @Date: 2021-11-08 21:59:11* @LastEditTime: 2021-11-12 23:44:19* @FilePath:c:\Users\timerring\AES.cpp*///定义轮常量表
static const unsigned char Rcon[10] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36 };//定义有限域*2乘法
static unsigned char x2time(unsigned char x)
{if (x & 0x80){return (((x << 1) ^ 0x1B) & 0xFF);}return x << 1;
}
//定义有限域*3乘法
static unsigned char x3time(unsigned char x)
{return (x2time(x) ^ x);
}
//定义有限域*4乘法
static unsigned char x4time(unsigned char x)
{return (x2time(x2time(x)));
}
//定义有限域*8乘法
static unsigned char x8time(unsigned char x)
{return (x2time(x2time(x2time(x))));
}
//定义有限域*9乘法
static unsigned char x9time(unsigned char x)
{return (x8time(x) ^ x);
}
//定义有限域*B乘法
static unsigned char xBtime(unsigned char x)
{return (x8time(x) ^ x2time(x) ^ x);
}
//定义有限域*D乘法
static unsigned char xDtime(unsigned char x)
{return (x8time(x) ^ x4time(x) ^ x);
}
//定义有限域*E乘法
static unsigned char xEtime(unsigned char x)
{return (x8time(x) ^ x4time(x) ^ x2time(x));
}
//s盒矩阵 Substitution Table
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,
};
//逆向S盒矩阵
static const unsigned char contrary_sbox[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,
};
//定义列混合操作
static void MixColumns(unsigned char* col)
{unsigned char tmp[4], xt[4];int i;for (i = 0; i < 4; i++, col += 4){  //col代表一列的基地址,col+4:下一列的基地址//xt[n]代表*2   xt[n]^col[n]代表*3   col[n]代表*1tmp[0] = x2time(col[0]) ^ x3time(col[1]) ^ col[2] ^ col[3];   //2 3 1 1tmp[1] = col[0] ^ x2time(col[1]) ^ x3time(col[2]) ^ col[3];   //1 2 3 1tmp[2] = col[0] ^ col[1] ^ x2time(col[2]) ^ x3time(col[3]);   //1 1 2 3tmp[3] = x3time(col[0]) ^ col[1] ^ col[2] ^ x2time(col[3]);   //3 1 1 2//修改后的值 直接在原矩阵上修改col[0] = tmp[0];col[1] = tmp[1];col[2] = tmp[2];col[3] = tmp[3];}
}
//定义逆向列混淆
static void Contrary_MixColumns(unsigned char* col)
{unsigned char tmp[4];unsigned char xt2[4];//colx2unsigned char xt4[4];//colx4unsigned char xt8[4];//colx8int x;for (x = 0; x < 4; x++, col += 4){tmp[0] = xEtime(col[0]) ^ xBtime(col[1]) ^ xDtime(col[2]) ^ x9time(col[3]);tmp[1] = x9time(col[0]) ^ xEtime(col[1]) ^ xBtime(col[2]) ^ xDtime(col[3]);tmp[2] = xDtime(col[0]) ^ x9time(col[1]) ^ xEtime(col[2]) ^ xBtime(col[3]);tmp[3] = xBtime(col[0]) ^ xDtime(col[1]) ^ x9time(col[2]) ^ xEtime(col[3]);col[0] = tmp[0];col[1] = tmp[1];col[2] = tmp[2];col[3] = tmp[3];}
}
//定义行移位操作:行左循环移位
static void ShiftRows(unsigned char* col)
{//正向行移位unsigned char t;//左移1位t = col[1]; col[1] = col[5]; col[5] = col[9]; col[9] = col[13]; col[13] = t;//左移2位,交换2次数字来实现t = col[2]; col[2] = col[10]; col[10] = t;t = col[6]; col[6] = col[14]; col[14] = t;//左移3位,相当于右移1次t = col[15]; col[15] = col[11]; col[11] = col[7]; col[7] = col[3]; col[3] = t;//第4行不移位
}
//逆向行移位
static void Contrary_ShiftRows(unsigned char* col)
{unsigned char t;t = col[13]; col[13] = col[9]; col[9] = col[5]; col[5] = col[1]; col[1] = t;t = col[2]; col[2] = col[10]; col[10] = t;t = col[6]; col[6] = col[14]; col[14] = t;t = col[3]; col[3] = col[7]; col[7] = col[11]; col[11] = col[15]; col[15] = t;//同理,第4行不移位
}
//定义s盒字节代换替换操作
static void SubBytes(unsigned char* col)
{//字节代换int x;for (x = 0; x < 16; x++){col[x] = sbox[col[x]];}
}
//逆向字节代换
static void Contrary_SubBytes(unsigned char* col)
{int x;for (x = 0; x < 16; x++){col[x] = contrary_sbox[col[x]];}
}
//密钥编排,16字节--->44列32bit密钥生成--> 11组16字节:分别用于11轮 轮密钥加运算
void ScheduleKey(unsigned char* inkey, unsigned char* outkey, int Nk, int Nr)
{//inkey:初始16字节密钥key//outkey:11组*16字节扩展密钥expansionkey//Nk:4列//Nr:10轮roundunsigned char temp[4], t;int x, i;/*copy the key*///第0组:[0-3]直接拷贝for (i = 0; i < (4 * Nk); i++){outkey[i] = inkey[i];}//第1-10组:[4-43]i = Nk;while (i < (4 * (Nr + 1))) //i=4~43 WORD 32bit的首字节地址,每一个4字节{//1次循环生成1个字节扩展密钥,4次循环生成一个WORD//temp:4字节数组:代表一个WORD密钥//i不是4的倍数的时候//每个temp = 每个outkey32bit = 4字节for (x = 0; x < 4; x++)temp[x] = outkey[(4 * (i - 1)) + x];    //i:32bit的首字节地址//i是4的倍数的时候if (i % Nk == 0){/*字循环:循环左移1字节 RotWord()*/t = temp[0]; temp[0] = temp[1]; temp[1] = temp[2]; temp[2] = temp[3]; temp[3] = t;/*字节代换:SubWord()*/for (x = 0; x < 4; x++){temp[x] = sbox[temp[x]];}/*轮常量异或:Rcon[j]*/temp[0] ^= Rcon[(i / Nk) - 1];}for (x = 0; x < 4; x++){outkey[(4 * i) + x] = outkey[(4 * (i - Nk)) + x] ^ temp[x];}++i;}
}
//定义轮密钥加操作
static void AddRoundKey(unsigned char* col, unsigned char* expansionkey, int round)//密匙加
{//扩展密钥:44*32bit =11*4* 4*8 =  16字节*11轮,每轮用16字节密钥//第0轮,只进行一次轮密钥加//第1-10轮,轮密钥加int x;for (x = 0; x < 16; x++){    //每1轮操作:4*32bit密钥 = 16个字节密钥col[x] ^= expansionkey[(round << 4) + x];}
}
//AES加密函数
void AesEncrypt(unsigned char* blk, unsigned char* expansionkey, int Nr)
{//加密一个区块//输入blk原文,直接在上面修改,输出blk密文//输入skey://输入Nr = 10轮int round;//第1轮之前:轮密钥加AddRoundKey(blk, expansionkey, 0);//第1-9轮:4类操作:字节代换、行移位、列混合、轮密钥加for (round = 1; round <= (Nr - 1); round++){SubBytes(blk);       //输入16字节数组,直接在原数组上修改ShiftRows(blk);      //输入16字节数组,直接在原数组上修改MixColumns(blk); //输入16字节数组,直接在原数组上修改AddRoundKey(blk, expansionkey, round);}//第10轮:不进行列混合SubBytes(blk);ShiftRows(blk);AddRoundKey(blk, expansionkey, Nr);
}
//AES 解密函数
void Contrary_AesEncrypt(unsigned char* blk, unsigned char* expansionkey, int Nr)
{int x;AddRoundKey(blk, expansionkey, Nr);Contrary_ShiftRows(blk);Contrary_SubBytes(blk);for (x = (Nr - 1); x >= 1; x--){AddRoundKey(blk, expansionkey, x);Contrary_MixColumns(blk);Contrary_ShiftRows(blk);Contrary_SubBytes(blk);}AddRoundKey(blk, expansionkey, 0);
}
int main(void) {unsigned char pt[17], key[17];//定义原文pt//定义密钥keyunsigned char expansionkey[15 * 16];int i;int j;printf("You are welcome to use the AES machine in SDU\n");printf("Please enter plaintext (length = 16):\n");scanf("%s", pt);printf("please input key:\n");scanf("%s", key);//加密过程ScheduleKey(key, expansionkey, 4, 10);//密钥扩展生成AesEncrypt(pt, expansionkey, 10);//调用AES 加密printf("ciphertext: ");    //输出密文for (i = 0; i < 16; i++){printf("%02x ", pt[i]);}printf("\n");printf("\n");//解密过程Contrary_AesEncrypt(pt, expansionkey, 10);//调用AES 解密printf("The decrypted plaintext is: ");//输出明文for (i = 0; i < 16; i++){printf("%c ", pt[i]);}printf("\n");printf("\n");while (1);return 0;
}

Test sample:

​ 此处假定测试明文为SDUinQINGDAOcity,设置测试密钥为iloveSDUforeverr,进行加密得到密文,再对密文进行解密,经验证可以得到明文,AES程序编写成功。


3. summary and harvest

我对AES密码的认识更加深入了,除了常见的加轮密钥以外,另外三个过程一起提供了混淆、扩散和非线性功能。这三个过程没有涉及密钥,就它们自身而言,并未提供算法的安全性。然而,该算法经历一个分组的XOR加密(轮密钥加),再对该分组混淆扩散(其他三个阶段),再接着又是XOR加密,如此交替进行,这种方式非常有效非常安全。其次,AES算法的每个阶段均可逆。对字节代替、行移位和列混淆,在解密算法中用它们相对应的逆函数。轮密钥加的逆就是用同样的轮密钥和分组相异或,其原理就是A⊕B⊕B = A。和大多数分组密码一样,AES解密算法按逆序利用扩展密钥,然而其解密算法和加密算法并不一样,这是由AES的特定结构决定的。

​ 而此次实验我印象最深的就是对于各轮AES加密循环(除最后一轮外)4个方法的编写:

  1. AddRoundKey — 矩阵中的每一个字节都与该次轮秘钥(round key)做XOR运算;每个子密钥由密钥生成方案产生。
  2. SubBytes — 通过非线性的替换函数,用查找表的方式把每个字节替换成对应的字节。
  3. ShiftRows — 将矩阵中的每个横列进行循环式移位。
  4. MixColumns — 为了充分混合矩阵中各个直行的操作。这个步骤使用线性转换来混合每列的四个字节。

​ 其中我觉得难处理的一个功能模块是列混淆。因为混淆变换实际上是使用乘法矩阵(其运算中涉及的加法和乘法都是定义在GF(28)上的加法和乘法,目的就是为了确保运算结果不会溢出定义域)。其次这个模块涉及到矩阵运算。好在本次实验矩阵的大小是4*4固定的,其中还要注意矩阵行、列计算的转换,所以还是很复杂的,很考验逻辑思维能力。

​ 还有一个难点就是密钥扩展。把每轮的密钥看成四个w[i],这一轮的第一个w[i]总是最难生成的。我们首先第n-1组第3列的4个字节循环左移1个字节;再对每个字节进行字节替代变换;再与轮常量相加;最后再与前一组该列相加。

​回顾起此AES密码编程,感慨颇多,从理论到实践,在这次的实验中,能够学到很多很多的东西,不仅仅巩固了课上所学过的AES知识,也学到了很多在书本上所没有学到过的知识。在实验操作与设计的过程中遇到问题也颇多,但可喜的是通过查找资料,阅读博客,查阅文献的方式,这些问题最终都得到了解决。

初学信息安全,可能存在错误之处,还请各位不吝赐教。

受于文本原因,本文相关算法实现工程无法展示出来,现已将资源上传,可自行点击下方链接下载。

AES加解密原理详解与算法实现工程文件

AES加解密原理详解与算法实现相关推荐

  1. ECC椭圆曲线加解密原理详解(配图)

    ECC椭圆曲线加解密原理详解(配图) 本文主要参照:ECC加密算法入门介绍及 ECC椭圆曲线详解(有具体实例) 前言: 椭圆曲线(ECC)加密原理跟RSA加解密原理比起来,可真是晦涩难懂.拜读了Kal ...

  2. RSA加解密过程详解

    RSA加解密过程详解 RSA加密是一种非对称加密,由一对密钥来完成加解密过程,分别为公钥和私钥. RSA的加密过程如下: (1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留.公钥为公开的,任何 ...

  3. 扩展Euclidean算法求乘法逆原理详解与算法实现

    [利用扩展Euclidean算法求乘法逆] 1. Equipment (1) operating system version :WIN 10 (2) CPU instruction set: x 6 ...

  4. 【胖虎的逆向之路】02——Android整体加壳原理详解实现

    [胖虎的逆向之路](02)--Android整体加壳原理详解&实现 Android Apk的加壳原理流程及详解 文章目录 [胖虎的逆向之路](02)--Android整体加壳原理详解& ...

  5. Hector SLAM 原理详解、算法解析

    目录 1.原理详解 2.算法解析 1.原理详解 Hector整体算法很直接,就是将激光点与已有的地图"对齐",即扫描匹配.扫描匹配就是使用当前帧与已经有的地图数据构建误差函数,使用 ...

  6. 多目标遗传算法NSGA-II原理详解及算法实现

    在接触学习多目标优化的问题上,经常会被提及到多目标遗传算法NSGA-II,网上也看到了很多人对该算法的总结,但真正讲解明白的以及配套用算法实现的文章很少,这里也对该算法进行一次详解与总结.会有侧重点的 ...

  7. RSA密码原理详解及算法实现(六步即可掌握)

    一.RSA算法概述 rsa算法是一种非对称加密算法,其安全性是建立在大素数难以分解的基础上的,即将两个大素数相乘十分容易,但想对其乘积进行分解却很困难,所以可以将其乘积公开作为加密密钥 二.RSA算法 ...

  8. 【密码学】DES加解密原理及其Java实现算法

    DES简介 DES(Data Encryption Standard)是对称加解密算法的一种,由IBM公司W.Tuchman和C.Meyer在上个世纪70年代开发. 该算法使用64位密钥(其中包含8位 ...

  9. AES 加密算法的原理详解

    本文转载https://blog.csdn.net/gulang03/article/details/81175854 本教程摘选自 https://blog.csdn.net/qq_28205153 ...

  10. python3 rsa加密_python3产生RSA秘钥对并执行加解密操作详解

    加密使用的是公钥对数据进行加密,而且当你使用一把1024bit的rsa公钥的时候,你一次只能加密最多117byte的数据,如果数据量超过这个数,可能会涉及到对数据进行分段加密的问题.而且现在rsa 1 ...

最新文章

  1. android ExpandableListView
  2. 网络营销外包——网络营销外包专员浅析网站首页设计需要注意哪些
  3. Ubuntu 下mysql service 启动问题
  4. 日志规范之slf4j整合JDK14以及Simple的使用
  5. 线段树求区间和(单点更新)
  6. paip.获取proxool的配置 xml读取通过jdk xml 初始化c3c0在代码中总结
  7. 8位16进制频率计设计实验--VHDL
  8. 4-30 HTML 细节摘录
  9. fcc jQuery 练习
  10. c# 鼠标控制图片大小
  11. 程序员常用的笔记软件——Typora快捷键
  12. Prometheus - 普罗米修斯 - 日志监控mtail尝试
  13. 从零开始的WTL入门教程(1) WTL的简介,环境搭建
  14. Seating Arrangement CSU - 1997 (思维题,是否存在n个数的序列,使得相邻啷个数的差绝对值大于d)
  15. P2P DHT sp
  16. MySQL—取当前周/下周/下下周的起始和结束时间
  17. 零基础学习web前端开发应该先学习什么
  18. 【单片机仿真项目】8×8 LED点阵图形显示
  19. 关于微信小程序请求http不到的问题
  20. 分治算法 --- 详解

热门文章

  1. 74HC04六通道反相器介绍
  2. 汕头大学计算机转专业,2021年汕头大学大一新生转专业及入学考试相关规定
  3. fpga驱动ad9854重大bug——已解决!
  4. 穿越六年艰难转型,明道云终于再获主流投资
  5. PyQt5在已运行界面中通过Botton按钮触发添加新的Botton按钮
  6. json解析天气预报java_Json解析-和风天气
  7. 通过vdi备份linux,Virtualbox复制(备份)带多个Snapshots的Vdi
  8. 【论文笔记】2022-CVPR-深度估计
  9. wei.getA()
  10. 慎用!闲鱼APP竟然成为了诈骗犯的庇护所!