AES加密算法c语言实现代码
- 格式:pdf
- 大小:64.70 KB
- 文档页数:7
AES算法C语言讲解与实现AES(Advanced Encryption Standard)是一种对称加密算法,被广泛应用于各种应用中,如保护通信、数据安全等。
AES算法采用分组密码的方式,将明文数据分成若干个大小相等的分组,然后对每个分组进行加密操作。
1. 密钥扩展(Key Expansion):AES算法中使用的密钥长度分为128位、192位和256位三种,密钥长度不同,密钥扩展的轮数也不同。
根据密钥长度,需要扩展成多少个轮密钥。
扩展过程中需要进行字节代换、循环左移、模2乘法等操作。
2. 子密钥生成(Subkey Generation):根据密钥扩展的结果,生成每一轮需要使用的子密钥。
3. 字节替换(SubBytes):将每个字节替换为S盒中对应的值。
S盒是一个固定的预先计算好的查找表。
4. 行移位(ShiftRows):对矩阵的行进行循环左移,左移的位数根据行数而定。
5. 列混合(MixColumns):将每列的四个字节进行混合。
混合操作包括乘法和异或运算。
6. 轮密钥加(AddRoundKey):将每一轮得到的结果与轮密钥进行异或运算。
以上就是AES算法的六个步骤的实现过程,下面我们来具体讲解一下。
首先,我们需要定义一些辅助函数,如字节代换函数、循环左移函数等。
```cuint8_t substitution(uint8_t byte) return sBox[byte];void shiftRows(uint8_t *state)uint8_t temp;//第二行循环左移1位temp = state[1];state[1] = state[5];state[5] = state[9];state[9] = state[13];state[13] = temp;//第三行循环左移2位temp = state[2];state[2] = state[10];state[10] = temp;temp = state[6];state[6] = state[14];state[14] = temp;//第四行循环左移3位temp = state[15];state[15] = state[11];state[11] = state[7];state[7] = state[3];state[3] = temp;void mixColumns(uint8_t *state)int i;uint8_t temp[4];for(i = 0; i < 4; i++)temp[0] = xTime(state[i * 4]) ^ xTime(state[i * 4 + 1]) ^ state[i * 4 + 1] ^state[i * 4 + 2] ^ state[i * 4 + 3];temp[1] = state[i * 4] ^ xTime(state[i * 4 + 1]) ^xTime(state[i * 4 + 2]) ^state[i * 4 + 2] ^ state[i * 4 + 3];temp[2] = state[i * 4] ^ state[i * 4 + 1] ^ xTime(state[i * 4 + 2]) ^xTime(state[i * 4 + 3]) ^ state[i * 4 + 3];temp[3] = xTime(state[i * 4]) ^ state[i * 4] ^ state[i * 4 + 1] ^state[i * 4 + 2] ^ xTime(state[i * 4 + 3]);state[i * 4] = temp[0];state[i * 4 + 1] = temp[1];state[i * 4 + 2] = temp[2];state[i * 4 + 3] = temp[3];}```接下来,我们实现密钥扩展和子密钥生成的过程。
AES加密算法实现C/S模式的通信设计任务:掌握AES的加密算法原理;掌握用socket编程实现C/S模式的加密通信。
设计内容:Socket编程实现客户端和服务器模式的通信;编程实现AES加解密的过程;将AES应用在C/S的通信中,对信息进行加密传输。
设计原理:1、socket编程实现C/S模式的通信,当用户在客户端发出请求时,会在服务器端做出相应的反应,并给出应答信息返回给客户端。
2、AES――对称密码新标准:高级加密标准。
对称密码体制的发展趋势将以分组密码为重点。
分组密码算法通常由密钥扩展算法和加密(解密)算法两部分组成。
密钥扩展算法将b字节用户主密钥扩展成r个子密钥。
加密算法由一个密码学上的弱函数f与r个子密钥迭代r次组成。
混乱和密钥扩散是分组密码算法设计的基本原则。
抵御已知明文的差分和线性攻击,可变长密钥和分组是该体制的设计要点。
AES是美国国家标准技术研究所NIST旨在取代DES的21世纪的加密标准。
AES的基本要求是,采用对称分组密码体制,密钥长度的最少支持为128、192、256,分组长度128位,算法应易于各种硬件和软件实现。
1998年NIST开始AES第一轮分析、测试和征集,共产生了15个候选算法。
1999年3月完成了第二轮AES 2的分析、测试。
最终将Rijndael数据加密算法作为高级加密标准AES。
在应用方面,尽管DES在安全上是脆弱的,但由于快速DES芯片的大量生产,使得DES仍能暂时继续使用,为提高安全强度,通常使用独立密钥的三级DES。
但是DES迟早要被AES代替。
3、AES的主要算法原理:AES 算法是基于置换和代替的。
置换是数据的重新排列,而代替是用一个单元数据替换另一个。
AES 使用了几种不同的技术来实现置换和替换。
为了阐明这些技术,让我们用 Figure 1 所示的数据讨论一个具体的 AES 加密例子。
下面是你要加密的128位值以及它们对应的索引数组:00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15192位密钥的值是:00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 170 1 2 3 4 5 6 7 8 9 10 1112 13 14 15 16 17 18 19 20 21 22 23Figure 2 S-盒( Sbox )当 AES 的构造函数(constructor)被调用时,用于加密方法的两个表被初始化。
#define BPOLY 0x1b //!< Lower 8 bits of (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1).#define BLOCKSIZE 16 //!< Block size in number of bytes.#define KEY_COUNT 3#if KEY_COUNT == 1#define KEYBITS 128 //!< Use AES128.#elif KEY_COUNT == 2#define KEYBITS 192 //!< Use AES196.#elif KEY_COUNT == 3#define KEYBITS 256 //!< Use AES256.#else#error Use 1, 2 or 3 keys!#endif#if KEYBITS == 128#define ROUNDS 10 //!< Number of rounds.#define KEYLENGTH 16 //!< Key length in number of bytes.#elif KEYBITS == 192#define ROUNDS 12 //!< Number of rounds.#define KEYLENGTH 24 //!< // Key length in number of bytes.#elif KEYBITS == 256#define ROUNDS 14 //!< Number of rounds.#define KEYLENGTH 32 //!< Key length in number of bytes.#else#error Key must be 128, 192 or 256 bits!#endif#define EXPANDED_KEY_SIZE (BLOCKSIZE * (ROUNDS+1)) //!< 176, 208 or 240 bytes.unsigned char AES_Key_Table[32] ={0xd0, 0x94, 0x3f, 0x8c, 0x29, 0x76, 0x15, 0xd8,0x20, 0x40, 0xe3, 0x27, 0x45, 0xd8, 0x48, 0xad,0xea, 0x8b, 0x2a, 0x73, 0x16, 0xe9, 0xb0, 0x49,0x45, 0xb3, 0x39, 0x28, 0x0a, 0xc3, 0x28, 0x3c,};unsigned char block1[256]; //!< Workspace 1.unsigned char block2[256]; //!< Worksapce 2.unsigned char tempbuf[256];unsigned char *powTbl; //!< Final location of exponentiation lookup table.unsigned char *logTbl; //!< Final location of logarithm lookup table. unsigned char *sBox; //!< Final location of s-box.unsigned char *sBoxInv; //!< Final location of inverse s-box. unsigned char *expandedKey; //!< Final location of expanded key.void CalcPowLog(unsigned char *powTbl, unsigned char *logTbl) {unsigned char i = 0;unsigned char t = 1;do {// Use 0x03 as root for exponentiation and logarithms.powTbl[i] = t;logTbl[t] = i;i++;// Muliply t by 3 in GF(2^8).t ^= (t << 1) ^ (t & 0x80 ? BPOLY : 0);}while( t != 1 ); // Cyclic properties ensure that i < 255.powTbl[255] = powTbl[0]; // 255 = '-0', 254 = -1, etc.}void CalcSBox( unsigned char * sBox ){unsigned char i, rot;unsigned char temp;unsigned char result;// Fill all entries of sBox[].i = 0;do {//Inverse in GF(2^8).if( i > 0 ){temp = powTbl[ 255 - logTbl[i] ];}else{temp = 0;}// Affine transformation in GF(2).result = temp ^ 0x63; // Start with adding a vector in GF(2).for( rot = 0; rot < 4; rot++ ){// Rotate left.temp = (temp<<1) | (temp>>7);// Add rotated byte in GF(2).result ^= temp;}// Put result in table.sBox[i] = result;} while( ++i != 0 );}void CalcSBoxInv( unsigned char * sBox, unsigned char * sBoxInv ) {unsigned char i = 0;unsigned char j = 0;// Iterate through all elements in sBoxInv using i.do {// Search through sBox using j.do {// Check if current j is the inverse of current i.if( sBox[ j ] == i ){// If so, set sBoxInc and indicate search finished.sBoxInv[ i ] = j;j = 255;}} while( ++j != 0 );} while( ++i != 0 );}void CycleLeft( unsigned char * row ){// Cycle 4 bytes in an array left once.unsigned char temp = row[0];row[0] = row[1];row[1] = row[2];row[2] = row[3];row[3] = temp;}void InvMixColumn( unsigned char * column ){unsigned char r0, r1, r2, r3;r0 = column[1] ^ column[2] ^ column[3];r1 = column[0] ^ column[2] ^ column[3];r2 = column[0] ^ column[1] ^ column[3];r3 = column[0] ^ column[1] ^ column[2];column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);r0 ^= column[0] ^ column[1];r1 ^= column[1] ^ column[2];r2 ^= column[2] ^ column[3];r3 ^= column[0] ^ column[3];column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);r0 ^= column[0] ^ column[2];r1 ^= column[1] ^ column[3];r2 ^= column[0] ^ column[2];r3 ^= column[1] ^ column[3];column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);column[0] ^= column[1] ^ column[2] ^ column[3];r0 ^= column[0];r1 ^= column[0];r2 ^= column[0];r3 ^= column[0];column[0] = r0;column[1] = r1;column[2] = r2;column[3] = r3;}void SubBytes( unsigned char * bytes, unsigned char count ){do {*bytes = sBox[ *bytes ]; // Substitute every byte in state.bytes++;} while( --count );}void InvSubBytesAndXOR( unsigned char * bytes, unsigned char * key, unsigned char count ){do {// *bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key.*bytes = block2[ *bytes ] ^ *key; // Use block2 directly. Increases speed.bytes++;key++;} while( --count );}void InvShiftRows( unsigned char * state ){unsigned char temp;// Note: State is arranged column by column.// Cycle second row right one time.temp = state[ 1 + 3*4 ];state[ 1 + 3*4 ] = state[ 1 + 2*4 ];state[ 1 + 2*4 ] = state[ 1 + 1*4 ];state[ 1 + 1*4 ] = state[ 1 + 0*4 ];state[ 1 + 0*4 ] = temp;// Cycle third row right two times.temp = state[ 2 + 0*4 ];state[ 2 + 0*4 ] = state[ 2 + 2*4 ];state[ 2 + 2*4 ] = temp;temp = state[ 2 + 1*4 ];state[ 2 + 1*4 ] = state[ 2 + 3*4 ];state[ 2 + 3*4 ] = temp;// Cycle fourth row right three times, ie. left once.temp = state[ 3 + 0*4 ];state[ 3 + 0*4 ] = state[ 3 + 1*4 ];state[ 3 + 1*4 ] = state[ 3 + 2*4 ];state[ 3 + 2*4 ] = state[ 3 + 3*4 ];state[ 3 + 3*4 ] = temp;}void InvMixColumns( unsigned char * state ){InvMixColumn( state + 0*4 );InvMixColumn( state + 1*4 );InvMixColumn( state + 2*4 );InvMixColumn( state + 3*4 );}void XORBytes( unsigned char * bytes1, unsigned char * bytes2, unsigned char count ) {do {*bytes1 ^= *bytes2; // Add in GF(2), ie. XOR.bytes1++;bytes2++;} while( --count );}void CopyBytes( unsigned char * to, unsigned char * from, unsigned char count ) {do {*to = *from;to++;from++;} while( --count );}void KeyExpansion( unsigned char * expandedKey ){unsigned char temp[4];unsigned char i;unsigned char Rcon[4] = { 0x01, 0x00, 0x00, 0x00 }; // Round constant.unsigned char * key = AES_Key_Table;// Copy key to start of expanded key.i = KEYLENGTH;do {*expandedKey = *key;expandedKey++;key++;} while( --i );// Prepare last 4 bytes of key in temp.expandedKey -= 4;temp[0] = *(expandedKey++);temp[1] = *(expandedKey++);temp[2] = *(expandedKey++);temp[3] = *(expandedKey++);// Expand key.i = KEYLENGTH;while( i < BLOCKSIZE*(ROUNDS+1) ){// Are we at the start of a multiple of the key size?if( (i % KEYLENGTH) == 0 ){CycleLeft( temp ); // Cycle left once.SubBytes( temp, 4 ); // Substitute each byte.XORBytes( temp, Rcon, 4 ); // Add constant in GF(2).*Rcon = (*Rcon << 1) ^ (*Rcon & 0x80 ? BPOLY : 0);}// Keysize larger than 24 bytes, ie. larger that 192 bits?#if KEYLENGTH > 24// Are we right past a block size?else if( (i % KEYLENGTH) == BLOCKSIZE ) {SubBytes( temp, 4 ); // Substitute each byte.}#endif// Add bytes in GF(2) one KEYLENGTH away.XORBytes( temp, expandedKey - KEYLENGTH, 4 );// Copy result to current 4 bytes.*(expandedKey++) = temp[ 0 ];*(expandedKey++) = temp[ 1 ];*(expandedKey++) = temp[ 2 ];*(expandedKey++) = temp[ 3 ];i += 4; // Next 4 bytes.}}void InvCipher( unsigned char * block, unsigned char * expandedKey ) {unsigned char round = ROUNDS-1;expandedKey += BLOCKSIZE * ROUNDS;XORBytes( block, expandedKey, 16 );expandedKey -= BLOCKSIZE;do {InvShiftRows( block );InvSubBytesAndXOR( block, expandedKey, 16 );expandedKey -= BLOCKSIZE;InvMixColumns( block );} while( --round );InvShiftRows( block );InvSubBytesAndXOR( block, expandedKey, 16 );}void aesDecInit(void){powTbl = block1;logTbl = block2;CalcPowLog( powTbl, logTbl );sBox = tempbuf;CalcSBox( sBox );expandedKey = block1;KeyExpansion( expandedKey );sBoxInv = block2; // Must be block2.CalcSBoxInv( sBox, sBoxInv );}void aesDecrypt( unsigned char * buffer, unsigned char * chainBlock ) {unsigned char temp[ BLOCKSIZE ];CopyBytes( temp, buffer, BLOCKSIZE );InvCipher( buffer, expandedKey );XORBytes( buffer, chainBlock, BLOCKSIZE );CopyBytes( chainBlock, temp, BLOCKSIZE );}unsigned char Multiply( unsigned char num, unsigned char factor ){unsigned char mask = 1;unsigned char result = 0;while( mask != 0 ){// Check bit of factor given by mask.if( mask & factor ){// Add current multiple of num in GF(2).result ^= num;}// Shift mask to indicate next bit.mask <<= 1;// Double num.num = (num << 1) ^ (num & 0x80 ? BPOLY : 0);}return result;}unsigned char DotProduct( unsigned char * vector1, unsigned char * vector2 ) {unsigned char result = 0;result ^= Multiply( *vector1++, *vector2++ );result ^= Multiply( *vector1++, *vector2++ );result ^= Multiply( *vector1++, *vector2++ );result ^= Multiply( *vector1 , *vector2 );return result;}void MixColumn( unsigned char * column ){unsigned char row[8] = {0x02, 0x03, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01};// Prepare first row of matrix twice, to eliminate need for cycling.unsigned char result[4];// Take dot products of each matrix row and the column vector.result[0] = DotProduct( row+0, column );result[1] = DotProduct( row+3, column );result[2] = DotProduct( row+2, column );result[3] = DotProduct( row+1, column );// Copy temporary result to original column.column[0] = result[0];column[1] = result[1];column[2] = result[2];column[3] = result[3];}void MixColumns( unsigned char * state ){MixColumn( state + 0*4 );MixColumn( state + 1*4 );MixColumn( state + 2*4 );MixColumn( state + 3*4 );}void ShiftRows( unsigned char * state ){unsigned char temp;// Note: State is arranged column by column.// Cycle second row left one time.temp = state[ 1 + 0*4 ];state[ 1 + 0*4 ] = state[ 1 + 1*4 ];state[ 1 + 1*4 ] = state[ 1 + 2*4 ];state[ 1 + 2*4 ] = state[ 1 + 3*4 ];state[ 1 + 3*4 ] = temp;// Cycle third row left two times.temp = state[ 2 + 0*4 ];state[ 2 + 0*4 ] = state[ 2 + 2*4 ];state[ 2 + 2*4 ] = temp;temp = state[ 2 + 1*4 ];state[ 2 + 1*4 ] = state[ 2 + 3*4 ];state[ 2 + 3*4 ] = temp;// Cycle fourth row left three times, ie. right once.temp = state[ 3 + 3*4 ];state[ 3 + 3*4 ] = state[ 3 + 2*4 ];state[ 3 + 2*4 ] = state[ 3 + 1*4 ];state[ 3 + 1*4 ] = state[ 3 + 0*4 ];state[ 3 + 0*4 ] = temp;}void Cipher( unsigned char * block, unsigned char * expandedKey ) {unsigned char round = ROUNDS-1;XORBytes( block, expandedKey, 16 );expandedKey += BLOCKSIZE;do {SubBytes( block, 16 );ShiftRows( block );MixColumns( block );XORBytes( block, expandedKey, 16 );expandedKey += BLOCKSIZE;} while( --round );SubBytes( block, 16 );ShiftRows( block );XORBytes( block, expandedKey, 16 );}void aesEncInit(void){powTbl = block1;logTbl = tempbuf;CalcPowLog( powTbl, logTbl );sBox = block2;CalcSBox( sBox );expandedKey = block1;KeyExpansion( expandedKey );}void aesEncrypt( unsigned char * buffer, unsigned char * chainBlock ) {XORBytes( buffer, chainBlock, BLOCKSIZE );Cipher( buffer, expandedKey );CopyBytes( chainBlock, buffer, BLOCKSIZE );}#include <string.h>void AES_Test(void){unsigned char dat[16]="0123456789ABCDEF";unsigned char chainCipherBlock[16];unsigned char i;for(i=0;i<32;i++) AES_Key_Table[i]=i;//做运算之前先要设置好密钥,这里只是设置密钥的DEMO。
AES算法加密C语言完整程序#包括〈字符串。
"#包括AES。
"#包括“大众。
”#定义字节无符号字符#定义 bpoly OxlB / /!〈下 8 位(x 8X 1 X4+3+1),艮[I (x+4+x + 3 + x+x)。
#定义块16 / /!〈字节大小的块大小。
#定义 keybits 128 / /!〈使用 AES128。
#定义轮10 / /!轮数。
#定义keylength 16 / /!字节长度的键长度。
字节XDATA酒店[256 ]; //!〈工作区1。
字节数据块 2 [ 256 ]; //! < worksapce 2。
字节数据* powtbl; / /!〈最后位置指数表。
字节数据* logtbl; / /!对数查找表的最后位置。
字节数据* S盒;/ /! < S盒的最终位置。
字节数据* sboxinv; / / !〈逆S盒的最终位置。
字节数据* Expandedkey; / /!〈扩展键的最后位置。
CalcPowLog (* powtbl 无效字节,字节* logtbl){我二0字节数据;T = 1字节数据;做{/ /使用0x03作为幕和对数根。
powtbl [我]=T;logtbl [T]二我;++;/ / muliply T 3在 GF (2 " 8)。
T " = (t<<l) " (T & 0x80? bpoly: 0);} (t! = 1);循环属性确保i〈 255o powtbl [ 255 ] = powtbl [ 0 ]; / / 255 = - 0, 254 - 1, 虚空CalcSBox (字节* S盒)字节数据我,腐;字节数据的温度;字节的数据结果;/ /填写参赛方法[]o我=0;做{/反转 GF (2X8)。
如果(i = 0) {温度=powtbl [ 255 ] logtbl [我];其他{ }温度=0;}/GF (2)的仿射变换。
AES加密C语言实现代码以下是一个简单的C语言实现AES加密算法的代码:```c#include <stdio.h>#include <stdlib.h>#include <stdint.h>//定义AES加密的轮数#define NR 10//定义AES加密的扩展密钥长度#define Nk 4//定义AES加密的行数和列数#define Nb 4//定义AES加密的状态矩阵typedef uint8_t state_t[4][4];//定义AES加密的S盒变换表static const uint8_t sbox[256] =//S盒变换表};//定义AES加密的轮常量表static const uint8_t Rcon[11] =//轮常量表};//定义AES加密的密钥扩展变换函数void KeyExpansion(const uint8_t* key, uint8_t* expandedKey) uint32_t* ek = (uint32_t*)expandedKey;uint32_t temp;//密钥拷贝到扩展密钥中for (int i = 0; i < Nk; i++)ek[i] = (key[4 * i] << 24) , (key[4 * i + 1] << 16) ,(key[4 * i + 2] << 8) , (key[4 * i + 3]);}//扩展密钥生成for (int i = Nk; i < Nb * (NR + 1); i++)temp = ek[i - 1];if (i % Nk == 0)//对上一个密钥的字节进行循环左移1位temp = (temp >> 8) , ((temp & 0xFF) << 24);//对每个字节进行S盒变换temp = (sbox[temp >> 24] << 24) , (sbox[(temp >> 16) & 0xFF] << 16) , (sbox[(temp >> 8) & 0xFF] << 8) , sbox[temp & 0xFF];// 取轮常量Rcontemp = temp ^ (Rcon[i / Nk - 1] << 24);} else if (Nk > 6 && i % Nk == 4)//对每个字节进行S盒变换temp = (sbox[temp >> 24] << 24) , (sbox[(temp >> 16) & 0xFF] << 16) , (sbox[(temp >> 8) & 0xFF] << 8) , sbox[temp & 0xFF];}//生成下一个密钥ek[i] = ek[i - Nk] ^ temp;}//定义AES加密的字节替换函数void SubBytes(state_t* state)for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[i][j] = sbox[(*state)[i][j]];}}//定义AES加密的行移位函数void ShiftRows(state_t* state) uint8_t temp;//第2行循环左移1位temp = (*state)[1][0];(*state)[1][0] = (*state)[1][1]; (*state)[1][1] = (*state)[1][2]; (*state)[1][2] = (*state)[1][3]; (*state)[1][3] = temp;//第3行循环左移2位temp = (*state)[2][0];(*state)[2][0] = (*state)[2][2]; (*state)[2][2] = temp;temp = (*state)[2][1];(*state)[2][1] = (*state)[2][3]; (*state)[2][3] = temp;//第4行循环左移3位temp = (*state)[3][0];(*state)[3][0] = (*state)[3][3];(*state)[3][3] = (*state)[3][2];(*state)[3][2] = (*state)[3][1];(*state)[3][1] = temp;//定义AES加密的列混淆函数void MixColumns(state_t* state)uint8_t temp, tmp, tm;for (int i = 0; i < 4; i++)tmp = (*state)[i][0];tm = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;temp = (*state)[i][0] ^ (*state)[i][1];(*state)[i][0] ^= temp ^ tm;temp = (*state)[i][1] ^ (*state)[i][2];(*state)[i][1] ^= temp ^ tm;temp = (*state)[i][2] ^ (*state)[i][3];(*state)[i][2] ^= temp ^ tm;temp = (*state)[i][3] ^ tmp;(*state)[i][3] ^= temp ^ tm;}//定义AES加密的轮密钥加函数void AddRoundKey(state_t* state, const uint8_t* roundKey) for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[j][i] ^= roundKey[i * 4 + j];}}//定义AES加密函数void AES_Encrypt(const uint8_t* plainText, const uint8_t* key, uint8_t* cipherText)state_t* state = (state_t*)cipherText;uint8_t expandedKey[4 * Nb * (NR + 1)];//密钥扩展KeyExpansion(key, expandedKey);//初始化状态矩阵for (int i = 0; i < 4; i++)for (int j = 0; j < 4; j++)(*state)[j][i] = plainText[i * 4 + j];}}//第1轮密钥加AddRoundKey(state, key);//迭代执行第2至第10轮加密for (int round = 1; round < NR; round++) SubBytes(state);ShiftRows(state);MixColumns(state);AddRoundKey(state, expandedKey + round * 16); }//执行第11轮加密SubBytes(state);ShiftRows(state);AddRoundKey(state, expandedKey + NR * 16);int maiuint8_t plainText[16] =//明文数据};uint8_t key[16] =//密钥数据};uint8_t cipherText[16];AES_Encrypt(plainText, key, cipherText);。
分组密码算法AES-128,192,256C语⾔实现第⼀版AES的C语⾔实现⼊门版AES分组密码算法中明⽂分组位128bits,密钥分组可以为128,192,256bits。
AES也是由最基本的变换单位——“轮”多次迭代⽽成的。
我们将 AES 中的轮变换计为 Round(State, RoundKey),State 表⽰消息矩阵;RoundKey 表⽰轮密钥矩阵。
⼀轮的完成将改变 State 矩阵中的元素,称为改变它的状态。
对于加密来说,输⼊到第⼀轮中的 State 就是明⽂消息矩阵,最后⼀轮输出的 State 就是对应的密⽂消息矩阵。
AES 的轮(除最后⼀轮外)变换有四个不同的变换组成,这些变化我们称之为内部轮函数, AES 的轮可表⽰成如下形式:Round(State, RoundKey){SubBytes(State);ShiftRows(State):MixColumns(State);AddRoundKey(State,RoundKey);}其中:ByteSub(State)称为字节代替变换、ShiftRow(State)称为⾏移位变、MixColumn(State)为列混合变换以及 AddRoundKey (State, RoundKey )为与⼦密钥与。
最后⼀轮略微的不同,将其记作 FinalRoundKey(State, RoundKey),相当于前⾯的Round(State, RoundKey)去掉 MixColumns(State)。
:加密过程:加密过程加密过程的伪代码:解密过程的伪代码:其中密钥长度不同,轮数不同,密钥编排扩展过程有所不同:下⾯是完整代码:#include "aes.h"const unsigned char sBox[16][16] = { 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};const unsigned char inv_sBox[16][16] = { 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};const unsigned char Rcon[16] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0xd8, 0xab, 0x4d, 0x9a, 0x2f };//轮常量表void SubBytes(unsigned char* in, const unsigned char table[16][16]){//字节替换for (int i = 0; i < 16; i++)in[i] = table[in[i] >> 4][in[i] & 0x0F];}void ShiftRows(unsigned char* in){//进⾏⾏移位unsigned char buffer[4] = { 0 };for (int i = 1; i < 4; i++){for (int j = 0; j < 4; j++)buffer[j] = in[((i + j) * 4 + i) % 16];for (int j = 0; j < 4; j++)in[4 * j + i] = buffer[j];}}void InvShiftRows(unsigned char* in){unsigned char buffer[4] = { 0 };for (int i = 1; i < 4; i++){for (int j = 0; j < 4; j++)buffer[j] = in[(4 * (4 - i + j) + i) % 16];for (int j = 0; j < 4; j++)in[4 * j + i] = buffer[j];}}unsigned char x2time(unsigned char a){//有限域*2乘法 The x2time() functionunsigned char res = (a << 1) ^ ((a & 0x80) ? 0x1b : 0x00);return res;}unsigned char x3time(unsigned char a){//3:0011return (x2time(a) ^ a);}unsigned char x4time(unsigned char a){//4:0100return (x2time(x2time(a)));}unsigned char x8time(unsigned char a){//8:1000return (x2time(x2time(x2time(a))));}unsigned char x9time(unsigned char a){//9:1001return (x8time(a) ^ a);unsigned char xBtime(unsigned char a){//B:1011return (x8time(a) ^ x3time(a));}unsigned char xDtime(unsigned char a){//D:1101return (x8time(a) ^ x4time(a) ^ a);}unsigned char xEtime(unsigned char a){//E:1110return (x8time(a) ^ x4time(a) ^ x2time(a));}void MixColumn(unsigned char* in){//进⾏列混合unsigned char tmp[4] = { 0 };for (int i = 0; i < 4; i++, in += 4){tmp[0] = x2time(in[0]) ^ x3time(in[1]) ^ in[2] ^ in[3];tmp[1] = in[0] ^ x2time(in[1]) ^ x3time(in[2]) ^ in[3];tmp[2] = in[0] ^ in[1] ^ x2time(in[2]) ^ x3time(in[3]);tmp[3] = x3time(in[0]) ^ in[1] ^ in[2] ^ x2time(in[3]);memcpy(in, tmp, 4);}}void InvMixColumn(unsigned char* in){//逆向列混合unsigned char tmp[4] = { 0 };for (int i = 0; i < 4; i++, in += 4){tmp[0] = xEtime(in[0]) ^ xBtime(in[1]) ^ xDtime(in[2]) ^ x9time(in[3]);tmp[1] = x9time(in[0]) ^ xEtime(in[1]) ^ xBtime(in[2]) ^ xDtime(in[3]);tmp[2] = xDtime(in[0]) ^ x9time(in[1]) ^ xEtime(in[2]) ^ xBtime(in[3]);tmp[3] = xBtime(in[0]) ^ xDtime(in[1]) ^ x9time(in[2]) ^ xEtime(in[3]);memcpy(in, tmp, 4);}}void AddRoundKey(unsigned char* in, const unsigned char* key){for (int i = 0; i < 16; i++)in[i] ^= key[i];}void rotWord(unsigned char* in){//将⼀个字进⾏左移循环⼀个单位unsigned char tmp = in[0];memcpy(in, in + 1, 3);in[3] = tmp;}void subWord(unsigned char* in){//每⼀个字进⾏字节替换for (int i = 0; i < 4; i++)in[i] = sBox[in[i] >> 4][in[i] & 0x0F];}static unsigned char roundKey[240] = { 0 };//最多是256bits,进⾏14轮迭代,roundKey中有15组,每⼀组16byte,最多是240bytes void SetKey(const unsigned char* key, const int Nk){int Nr = Nk + 6;memcpy(roundKey, key, 4 * Nk);//将最初的key拷贝到roundKey数组的最开始,每⼀个乘上4因为按字来计算,1字=4bytefor (int i = Nk; i < (Nr + 1) * 4; i++){unsigned char buffer[4] = { 0 };memcpy(buffer, roundKey + (i - 1) * 4, 4);if (i%Nk == 0){rotWord(buffer);subWord(buffer);buffer[0] ^= Rcon[i / Nk];}if ((i%Nk == 4) && Nk>6)subWord(buffer);for (int j = 0; j < 4; j++)roundKey[4 * i + j] = buffer[j] ^ roundKey[(i - Nk) * 4 + j];}}void encryptAES(unsigned char* out, const unsigned char* in, const unsigned char* key, const int keyLen){int Nk = keyLen >> 2;int Nr = Nk + 6;SetKey(key, Nk);memcpy(out, in, 16);AddRoundKey(out, roundKey);for (int i = 1; i <= Nr; i++){//进⾏Nr轮变换,最后⼀个Nr轮不进⾏列混合SubBytes(out, sBox);ShiftRows(out);if (i != Nr)MixColumn(out);AddRoundKey(out, roundKey + 16 * i);}void decryptAES(unsigned char* out, const unsigned char* in, const unsigned char* key, const int keyLen){ int Nk = keyLen >> 2;int Nr = Nk + 6;SetKey(key, Nk);memcpy(out, in, 16);AddRoundKey(out, roundKey + Nr * 16);for (int i = Nr - 1; i >= 0; i--){InvShiftRows(out);SubBytes(out, inv_sBox);AddRoundKey(out, roundKey + 16 * i);if (i != 0)InvMixColumn(out);}}aes.h头⽂件:#pragma once#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <string.h>#ifdef __cplusplusextern"C"{#endifvoid encryptAES(unsigned char* out, const unsigned char* in, const unsigned char* key, const int keyLen);void decryptAES(unsigned char* out, const unsigned char* in, const unsigned char* key, const int keyLen); #ifdef __cplusplus}#endif运⾏结果:密钥是128Bits时:密钥是192bits时:密钥是256bits时:。
基于C语⾔实现的aes256加密算法⽰例本⽂实例讲述了基于C语⾔实现的aes256加密算法。
分享给⼤家供⼤家参考,具体如下:aes256.h:#ifndef uint8_t#define uint8_t unsigned char#endif#ifdef __cplusplusextern "C" {#endiftypedef struct {uint8_t key[32];uint8_t enckey[32];uint8_t deckey[32];} aes256_context;void aes256_init(aes256_context *, uint8_t * );void aes256_done(aes256_context *);void aes256_encrypt_ecb(aes256_context *, uint8_t * );void aes256_decrypt_ecb(aes256_context *, uint8_t * );#ifdef __cplusplus}#endifaes256.c:#include "aes256.h"#define F(x) (((x)<<1) ^ ((((x)>>7) & 1) * 0x1b))#define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0))// #define BACK_TO_TABLES#ifdef BACK_TO_TABLESconst uint8_t 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};const uint8_t sboxinv[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};#define rj_sbox(x) sbox[(x)]#define rj_sbox_inv(x) sboxinv[(x)]#elseuint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3{uint8_t atb = 1, z;while (x--) {z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;} return atb;}uint8_t gf_log(uint8_t x) // calculate logarithm gen 3{uint8_t atb = 1, i = 0, z;do {if (atb == x) break;z = atb; atb <<= 1; if (z & 0x80) atb^= 0x1b; atb ^= z;} while (++i > 0);return i;}uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse{return (x) ? gf_alog(255 - gf_log(x)) : 0;}uint8_t rj_sbox(uint8_t x){uint8_t y, sb;sb = y = gf_mulinv(x);y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;y = (y<<1)|(y>>7); sb ^= y; y = (y<<1)|(y>>7); sb ^= y;return (sb ^ 0x63);}uint8_t rj_sbox_inv(uint8_t x){uint8_t y, sb;y = x ^ 0x63;sb = y = (y<<1)|(y>>7);y = (y<<2)|(y>>6); sb ^= y; y = (y<<3)|(y>>5); sb ^= y;return gf_mulinv(sb);}#endifuint8_t rj_xtime(uint8_t x){return (x & 0x80) ? ((x << 1) ^ 0x1b) : (x << 1);}void aes_subBytes(uint8_t *buf){register uint8_t i = 16;while (i--) buf[i] = rj_sbox(buf[i]);}void aes_subBytes_inv(uint8_t *buf){register uint8_t i = 16;while (i--) buf[i] = rj_sbox_inv(buf[i]);}void aes_addRoundKey(uint8_t *buf, uint8_t *key){register uint8_t i = 16;while (i--) buf[i] ^= key[i];}void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk){register uint8_t i = 16;while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16+i] = key[16 + i];}void aes_shiftRows(uint8_t *buf){register uint8_t i, j;i = buf[1]; buf[1] = buf[5]; buf[5] = buf[9]; buf[9] = buf[13]; buf[13] = i;i = buf[10]; buf[10] = buf[2]; buf[2] = i;j = buf[3]; buf[3] = buf[15]; buf[15] = buf[11]; buf[11] = buf[7]; buf[7] = j; j = buf[14]; buf[14] = buf[6]; buf[6] = j;}void aes_shiftRows_inv(uint8_t *buf){register uint8_t i, j;i = buf[1]; buf[1] = buf[13]; buf[13] = buf[9]; buf[9] = buf[5]; buf[5] = i;i = buf[2]; buf[2] = buf[10]; buf[10] = i;j = buf[3]; buf[3] = buf[7]; buf[7] = buf[11]; buf[11] = buf[15]; buf[15] = j; j = buf[6]; buf[6] = buf[14]; buf[14] = j;}void aes_mixColumns(uint8_t *buf){register uint8_t i, a, b, c, d, e;for (i = 0; i < 16; i += 4){a = buf[i];b = buf[i + 1];c = buf[i + 2];d = buf[i + 3];e = a ^ b ^ c ^ d;buf[i] ^= e ^ rj_xtime(a^b); buf[i+1] ^= e ^ rj_xtime(b^c);buf[i+2] ^= e ^ rj_xtime(c^d); buf[i+3] ^= e ^ rj_xtime(d^a);}}void aes_mixColumns_inv(uint8_t *buf){register uint8_t i, a, b, c, d, e, x, y, z;for (i = 0; i < 16; i += 4){a = buf[i];b = buf[i + 1];c = buf[i + 2];d = buf[i + 3];e = a ^ b ^ c ^ d;z = rj_xtime(e);x = e ^ rj_xtime(rj_xtime(z^a^c)); y = e ^ rj_xtime(rj_xtime(z^b^d));buf[i] ^= x ^ rj_xtime(a^b); buf[i+1] ^= y ^ rj_xtime(b^c);buf[i+2] ^= x ^ rj_xtime(c^d); buf[i+3] ^= y ^ rj_xtime(d^a);}}void aes_expandEncKey(uint8_t *k, uint8_t *rc){register uint8_t i;k[0] ^= rj_sbox(k[29]) ^ (*rc);k[1] ^= rj_sbox(k[30]);k[2] ^= rj_sbox(k[31]);k[3] ^= rj_sbox(k[28]);*rc = F( *rc);for(i = 4; i < 16; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];k[16] ^= rj_sbox(k[12]);k[17] ^= rj_sbox(k[13]);k[18] ^= rj_sbox(k[14]);k[19] ^= rj_sbox(k[15]);for(i = 20; i < 32; i += 4) k[i] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];}void aes_expandDecKey(uint8_t *k, uint8_t *rc){uint8_t i;for(i = 28; i > 16; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];k[16] ^= rj_sbox(k[12]);k[17] ^= rj_sbox(k[13]);k[18] ^= rj_sbox(k[14]);k[19] ^= rj_sbox(k[15]);for(i = 12; i > 0; i -= 4) k[i+0] ^= k[i-4], k[i+1] ^= k[i-3],k[i+2] ^= k[i-2], k[i+3] ^= k[i-1];*rc = FD(*rc);k[0] ^= rj_sbox(k[29]) ^ (*rc);k[1] ^= rj_sbox(k[30]);k[2] ^= rj_sbox(k[31]);k[3] ^= rj_sbox(k[28]);}void aes256_init(aes256_context *ctx, uint8_t *k){uint8_t rcon = 1;register uint8_t i;for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i];for (i = 8;--i;) aes_expandEncKey(ctx->deckey, &rcon);}void aes256_done(aes256_context *ctx){register uint8_t i;for (i = 0; i < sizeof(ctx->key); i++)ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0;}void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf){uint8_t i, rcon;aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key);for(i = 1, rcon = 1; i < 14; ++i){aes_subBytes(buf);aes_shiftRows(buf);aes_mixColumns(buf);if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]);else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key); }aes_subBytes(buf);aes_shiftRows(buf);aes_expandEncKey(ctx->key, &rcon);aes_addRoundKey(buf, ctx->key);}void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf){uint8_t i, rcon;aes_addRoundKey_cpy(buf, ctx->deckey, ctx->key);aes_shiftRows_inv(buf);aes_subBytes_inv(buf);for (i = 14, rcon = 0x80; --i;){if( ( i & 1 ) ){aes_expandDecKey(ctx->key, &rcon);aes_addRoundKey(buf, &ctx->key[16]);}else aes_addRoundKey(buf, ctx->key);aes_mixColumns_inv(buf);aes_shiftRows_inv(buf);aes_subBytes_inv(buf);}aes_addRoundKey( buf, ctx->key);}demo.c:#include#include#include "aes256.h"#define DUMP(s, i, buf, sz) {printf(s); /for (i = 0; i < (sz);i++) /printf("x ", buf[i]); /printf("/n");}int main (int argc, char *argv[]){aes256_context ctx;uint8_t key[32];uint8_t buf[16], i;for (i = 0; i < sizeof(buf);i++) buf[i] = i * 16 + i;for (i = 0; i < sizeof(key);i++) key[i] = i;DUMP("txt: ", i, buf, sizeof(buf));DUMP("key: ", i, key, sizeof(key));printf("---/n");aes256_init(&ctx, key);aes256_encrypt_ecb(&ctx, buf);DUMP("enc: ", i, buf, sizeof(buf));printf("tst: 8e a2 b7 ca 51 67 45 bf ea fc 49 90 4b 49 60 89/n");aes256_init(&ctx, key);aes256_decrypt_ecb(&ctx, buf);DUMP("dec: ", i, buf, sizeof(buf));aes256_done(&ctx);return 0;}PS:关于加密解密感兴趣的朋友还可以参考本站在线⼯具:希望本⽂所述对⼤家C语⾔程序设计有所帮助。
一、介绍C语言是一种广泛应用的计算机编程语言,而AES256 ECB算法是一种高级加密标准,也是一种对称加密算法。
本文将详细介绍C语言中实现AES256 ECB算法的方式及其原理。
二、AES256 ECB算法AES256 ECB算法是一种对称加密算法,使用256位的密钥进行加密和解密。
ECB(Electronic Codebook)模式是AES加密算法中最简单的模式,它将整个消息分割成固定长度的块,然后对每个块进行加密。
1. 加密过程- 对明文进行填充,使其长度为块的整数倍。
- 将填充后的明文分割成若干块,每个块的长度与密钥长度相同。
- 接下来,对每个块使用AES256算法进行加密,并将加密结果拼接在一起,得到密文。
2. 解密过程- 将密文分割成若干块,每个块的长度与密钥长度相同。
- 对每个块使用AES256算法进行解密,并将解密结果拼接在一起。
- 去除填充得到明文。
三、C语言中实现AES256 ECB算法的方式在C语言中实现AES256 ECB算法可以借助开源的加密库,例如openssl库。
以下是使用openssl库实现AES256 ECB算法的示例代码:```#include <openssl/aes.h>void aes_encrypt_ecb(const unsigned char *pl本人ntext, const unsigned char *key, unsigned char *ciphertext) {AES_KEY aes_key;AES_set_encrypt_key(key, 256, aes_key);AES_encrypt(pl本人ntext, ciphertext, aes_key);}void aes_decrypt_ecb(const unsigned char *ciphertext, const unsigned char *key, unsigned char *pl本人ntext) {AES_KEY aes_key;AES_set_decrypt_key(key, 256, aes_key);AES_decrypt(ciphertext, pl本人ntext, aes_key);}```以上代码中,aes_encrypt_ecb函数用于对明文进行加密,aes_decrypt_ecb函数用于对密文进行解密。