AES128加密算法的实现(C/Java/C#)

最近项目中有一个需求,实现AES128的加密算法,用于硬件和平台的通信。硬件加密部分使用C语言完成、平台有两种不同的环境:java(Linux)和C#(Windows)。在网上搜集了一些资料,有人实现过纯C代码的AES加密解密算法,这样实际上有一种较为简单的解决思路:加密部分直接拿过来使用;解密部分可以打包为dll(windows环境)或SO(linux环境)库供平台调用。但考虑到环境的兼容性等问题最后决定分别在Java和C#中实现算法的解密部分。

AES128算法的实现参考如下代码:https://github.com/openluopworld/aes_128

一、数据加密部分,直接调用项目中的加密函数即可。

二、数据解密部分,也就是用Java和C#将aes_encrypt_128函数重新实现。

2.1、Java中实现aes_encrypt_128

和C语言相比在Java中实现解密算法需要注意几个细节:

1、Java中没有数组指针的概念:C语言的数组指针主要是方便控制计算的范围,这个功能实际上可以用数组的索引来实现,

2、C语言中的uint8_t 也就是unsigned char在Java中与之对应的是byte,但Java的byte取值为-128-127:0xf2由于超出127,在java中默认是int类型,这里在声明的时候需要强制类型转换。

同时为了和C中的计算对应,在超过127的时候可以与0x0FF做逻辑与(Java中的位运算会将byte转换为int然后进行计算)处理,转换为int操作,这里做逻辑与运算的目的是为了将-128-127的范围转换为0-255的范围,在Java中这一步十分重要,因为java没有无符号的概念,如果不处理byte的负数转换为整型后仍为负数,这在大部分的时候并不是我们想要的结果。

代码如下:

package com.run.gradewall.model;

import java.util.Arrays;

/*
 *
 * 主要是解密、解密,10轮产生轮秘钥的函数,
 * 加密与解密函数分别调用产生轮秘钥的函数,每轮的输入与轮密钥异或一次,轮秘钥产生函数需要调用S盒函数,进行映射
 * 变量: *roundkeys存放产生轮秘钥的指针,*plaintext存放明文的指针,*ciphertext存放密文的指针,*state运行加密操作的4*4矩阵

 *
 */

public class AES {

/*
 * 作用:进行映射操作的S盒
 * 类型:静态的一个Byte的数据
 */
    private static byte[] SBOX = new byte[] {
            //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
            0x63, 0x7c, 0x77, 0x7b, (byte) 0xf2, 0x6b, 0x6f, (byte) 0xc5, 0x30, 0x01, 0x67, 0x2b, (byte) 0xfe, (byte) 0xd7, (byte) 0xab, 0x76,
            (byte)0xca, (byte)0x82, (byte)0xc9, 0x7d, (byte)0xfa, 0x59, 0x47, (byte)0xf0, (byte)0xad, (byte)0xd4, (byte)0xa2, (byte)0xaf, (byte)0x9c, (byte)0xa4, 0x72, (byte)0xc0,
            (byte)0xb7, (byte)0xfd, (byte)0x93, 0x26, 0x36, 0x3f, (byte)0xf7, (byte)0xcc, 0x34, (byte)0xa5, (byte)0xe5, (byte)0xf1, 0x71, (byte)0xd8, 0x31, 0x15,
            0x04, (byte)0xc7, 0x23, (byte)0xc3, 0x18, (byte)0x96, 0x05, (byte)0x9a, 0x07, 0x12, (byte)0x80, (byte)0xe2, (byte)0xeb, 0x27, (byte)0xb2, 0x75,
            0x09, (byte)0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, (byte)0xa0, 0x52, 0x3b, (byte)0xd6, (byte) 0xb3, 0x29, (byte)0xe3, 0x2f, (byte)0x84,
            0x53, (byte)0xd1, 0x00, (byte)0xed, 0x20, (byte)0xfc, (byte)0xb1, 0x5b, 0x6a, (byte)0xcb, (byte)0xbe, 0x39, 0x4a, 0x4c, 0x58, (byte)0xcf,
            (byte)0xd0, (byte)0xef, (byte)0xaa, (byte)0xfb, 0x43, 0x4d, 0x33, (byte)0x85, 0x45, (byte)0xf9, 0x02, 0x7f, 0x50, 0x3c, (byte)0x9f, (byte)0xa8,
            0x51, (byte)0xa3, 0x40, (byte)0x8f, (byte)0x92, (byte)0x9d, 0x38, (byte)0xf5, (byte)0xbc, (byte)0xb6, (byte)0xda, 0x21, 0x10, (byte)0xff, (byte)0xf3, (byte)0xd2,
            (byte)0xcd, 0x0c, 0x13, (byte)0xec, 0x5f, (byte)0x97, 0x44, 0x17, (byte)0xc4, (byte)0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
            0x60, (byte)0x81, 0x4f, (byte)0xdc, 0x22, 0x2a, (byte)0x90, (byte)0x88, 0x46, (byte)0xee, (byte)0xb8, 0x14, (byte)0xde, 0x5e, 0x0b, (byte)0xdb,
            (byte)0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, (byte)0xc2, (byte)0xd3, (byte)0xac, 0x62, (byte)0x91, (byte)0x95, (byte)0xe4, 0x79,
            (byte)0xe7, (byte)0xc8, 0x37, 0x6d, (byte)0x8d, (byte)0xd5, 0x4e, (byte)0xa9, 0x6c, 0x56, (byte)0xf4, (byte)0xea, 0x65, 0x7a, (byte)0xae, 0x08,
            (byte)0xba, 0x78, 0x25, 0x2e, 0x1c, (byte)0xa6, (byte)0xb4, (byte)0xc6, (byte)0xe8, (byte)0xdd, 0x74, 0x1f, 0x4b, (byte)0xbd, (byte)0x8b, (byte)0x8a,
            0x70, 0x3e, (byte)0xb5, 0x66, 0x48, 0x03, (byte)0xf6, 0x0e, 0x61, 0x35, 0x57, (byte)0xb9, (byte)0x86, (byte)0xc1, 0x1d, (byte)0x9e,
            (byte)0xe1, (byte)0xf8, (byte)0x98, 0x11, 0x69, (byte)0xd9, (byte)0x8e, (byte)0x94, (byte)0x9b, 0x1e, (byte)0x87, (byte)0xe9, (byte)0xce, 0x55, 0x28, (byte)0xdf,
            (byte)0x8c, (byte)0xa1, (byte)0x89, 0x0d, (byte)0xbf, (byte)0xe6, 0x42, 0x68, 0x41, (byte)0x99, 0x2d, 0x0f, (byte)0xb0, 0x54, (byte)0xbb, 0x16 };
    /*
     * 作用:进行逆映射的S盒
     * 类型:静态的一个Byte的数据
     */
    private static byte[] INV_SBOX = new byte[] {
            0x52, 0x09, 0x6a, (byte) 0xd5, 0x30, 0x36, (byte) 0xa5, 0x38, (byte) 0xbf, 0x40, (byte) 0xa3, (byte) 0x9e, (byte) 0x81, (byte) 0xf3, (byte) 0xd7, (byte) 0xfb,
            0x7c, (byte) 0xe3, 0x39, (byte) 0x82, (byte) 0x9b, 0x2f, (byte) 0xff, (byte) 0x87, 0x34, (byte) 0x8e, 0x43, 0x44, (byte) 0xc4, (byte) 0xde, (byte) 0xe9, (byte) 0xcb,
            0x54, 0x7b, (byte) 0x94, 0x32, (byte) 0xa6, (byte) 0xc2, 0x23, 0x3d, (byte) 0xee, 0x4c, (byte) 0x95, 0x0b, 0x42, (byte) 0xfa, (byte) 0xc3, 0x4e,
            0x08, 0x2e, (byte) 0xa1, 0x66, 0x28, (byte) 0xd9, 0x24, (byte) 0xb2, 0x76, 0x5b, (byte) 0xa2, 0x49, 0x6d, (byte) 0x8b, (byte) 0xd1, 0x25,
            0x72, (byte) 0xf8, (byte) 0xf6, 0x64, (byte) 0x86, 0x68, (byte) 0x98, 0x16, (byte) 0xd4, (byte) 0xa4, 0x5c, (byte) 0xcc, 0x5d, 0x65, (byte) 0xb6, (byte) 0x92,
            0x6c, 0x70, 0x48, 0x50, (byte) 0xfd, (byte) 0xed, (byte) 0xb9, (byte) 0xda, 0x5e, 0x15, 0x46, 0x57, (byte) 0xa7, (byte) 0x8d, (byte) 0x9d, (byte) 0x84,
            (byte) 0x90, (byte) 0xd8, (byte) 0xab, 0x00, (byte) 0x8c, (byte) 0xbc, (byte) 0xd3, 0x0a, (byte) 0xf7, (byte) 0xe4, 0x58, 0x05, (byte) 0xb8, (byte) 0xb3, 0x45, 0x06,
            (byte) 0xd0, 0x2c, 0x1e, (byte) 0x8f, (byte) 0xca, 0x3f, 0x0f, 0x02, (byte) 0xc1, (byte) 0xaf, (byte) 0xbd, 0x03, 0x01, 0x13, (byte) 0x8a, 0x6b,
            0x3a, (byte) 0x91, 0x11, 0x41, 0x4f, 0x67, (byte) 0xdc, (byte) 0xea, (byte) 0x97, (byte) 0xf2, (byte) 0xcf, (byte) 0xce, (byte) 0xf0, (byte) 0xb4, (byte) 0xe6, 0x73,
            (byte) 0x96, (byte) 0xac, 0x74, 0x22, (byte) 0xe7, (byte) 0xad, 0x35, (byte) 0x85, (byte) 0xe2, (byte) 0xf9, 0x37, (byte) 0xe8, 0x1c, 0x75, (byte) 0xdf, 0x6e,
            0x47, (byte) 0xf1, 0x1a, 0x71, 0x1d, 0x29, (byte) 0xc5, (byte) 0x89, 0x6f, (byte) 0xb7, 0x62, 0x0e, (byte) 0xaa, 0x18, (byte) 0xbe, 0x1b,
            (byte) 0xfc, 0x56, 0x3e, 0x4b, (byte) 0xc6, (byte) 0xd2, 0x79, 0x20, (byte) 0x9a, (byte) 0xdb, (byte) 0xc0, (byte) 0xfe, 0x78, (byte) 0xcd, 0x5a, (byte) 0xf4,
            0x1f, (byte) 0xdd, (byte) 0xa8, 0x33, (byte) 0x88, 0x07, (byte) 0xc7, 0x31, (byte) 0xb1, 0x12, 0x10, 0x59, 0x27, (byte) 0x80, (byte) 0xec, 0x5f,
            0x60, 0x51, 0x7f, (byte) 0xa9, 0x19, (byte) 0xb5, 0x4a, 0x0d, 0x2d, (byte) 0xe5, 0x7a, (byte) 0x9f, (byte) 0x93, (byte) 0xc9, (byte) 0x9c, (byte) 0xef,
            (byte) 0xa0, (byte) 0xe0, 0x3b, 0x4d, (byte) 0xae, 0x2a, (byte) 0xf5, (byte) 0xb0, (byte) 0xc8, (byte) 0xeb, (byte) 0xbb, 0x3c, (byte) 0x83, 0x53, (byte) 0x99, 0x61,
            0x17, 0x2b, 0x04, 0x7e, (byte) 0xba, 0x77, (byte) 0xd6, 0x26, (byte) 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };

 /*
     * 作用:秘钥扩展中要进行异或操作的一维数组
     * 类型:静态的一个Byte的数据
 */
    private static byte[] RC = new byte[] {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, (byte) 0x80, 0x1b, 0x36};
    
    
/*
     * 作用:初始设置的秘钥,为16个Byte
     * 类型:一个Byte的数据
*/

    private static byte[] key = new byte[] { 0x40, 0x41, 0x40, 0x41, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x41, 0x40, 0x41, 0x39};

    
/*
    * 作用:存放秘钥扩展后的轮秘钥,为44个字,共176Byte
    * 类型:一个Byte的数据
*/
	private static int AES_BLOCK_SIZE = 16;
	private static int AES_ROUNDS = 10;
    private static byte[] roundkeys = new byte[176];// AES-128 has 10 rounds, and there is a AddRoundKey before first round. (10+1)x16=176.

	



/*
 * 功能:  由初始秘钥产生轮秘钥,将产生的轮秘钥放在*roundkeys中
 * 参数:  传入初始秘钥的地址,和轮秘钥的地址
 * 返回值:  无
*/
	private void aes_key_schedule_128(byte[] key, byte[]roundkeys)
	{
	
		byte[] temp = new byte[4];
		int last4bytes = 12; // point to the last 4 bytes of one round
		int i;
		int index =0;//用于循环计算
	
		for (i = 0; i < 16; i++)
		{
			roundkeys[index++] = key[i];
		}
		
	
		//利用索引解决C中的指针问题
		int index_l4b = 0;
		
		
		for (i = 0; i < 10; i++)
		{	//更新代替引用
			// k0-k3 for next round
			//java中的byte-127--128需要&0x0FF处理
			temp[3] = SBOX[roundkeys[last4bytes+index_l4b++]&0x0FF];
			temp[0] = SBOX[roundkeys[last4bytes+index_l4b++]&0x0FF];
			temp[1] = SBOX[roundkeys[last4bytes+index_l4b++]&0x0FF];
			temp[2] = SBOX[roundkeys[last4bytes+index_l4b++]&0x0FF];
			temp[0] ^= RC[i];
			
			int lastround = 16*i;
	
			roundkeys[index++] = (byte) (temp[0] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (temp[1] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (temp[2] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (temp[3] ^ roundkeys[lastround++]);
			// k4-k7 for next round        
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			// k8-k11 for next round
	
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			// k12-k15 for next round
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
			roundkeys[index++] = (byte) (roundkeys[last4bytes+index_l4b++] ^ roundkeys[lastround++]);
		}
	}


/*
 * 功能:  将矩阵中的每个横列进行逆循环式移位
 * 描述:
 *  Row0: s0  s4  s8  s12   >>> 0 byte
 *  Row1: s1  s5  s9  s13   >>> 1 byte
 *  Row2: s2  s6  s10 s14   >>> 2 bytes
 *  Row3: s3  s7  s11 s15   >>> 3 bytes
 * 参数:  传入一个4*4的矩阵
 * 返回值:  无
*/
	private void inv_shift_rows(byte[] state)
	{
		byte temp;
		//row1
		temp = state[13];
		state[13] = state[9];
		state[9] = state[5];
		state[5] = state[1];
		state[1] = temp;
		//row2
		
		temp = state[14];
		state[14] = state[6];
		state[6] = temp;
		temp = state[10];
		state[10] = state[2];
		state[2] = temp;
		// row3
		temp = state[3];
		state[3] = state[7];
		state[7] = state[11];
		state[11] = state[15];
		state[15] = temp;
		
		

	}
	
	
	
/*
	 * 功能:  加密或解密中使用的多项式(x^8 + x^4 + x^3 + x + 1 = 0)更快处理数据
	 * 不使用mul(uint8_t a, uint8_t b),而使用mul2(int8_t a)
	 * 参数:  传入要处理的一个Byte数据
	 * 返回值:  直接返回处理后的数据
*/
	private final byte mul2(byte a)
	{
		//考虑java中byte有符号
		return (byte) ((a & 0x80) != 0 ? (( (a & 0x0FF) << 1) ^ 0x1b) : ( (a & 0x0FF) << 1));
	}
	
	
/*
* 功能:  对密文进行解密的解密函数,将解密后的明文放在*plaintext中
* 参数:  传入轮秘钥的地址、明文、密文的地址
* 返回值:  无
*/
	
	private void aes_decrypt_128(byte[] roundkeys, byte[] ciphertext, byte[] plaintext)
	{
		byte[] tmp = new byte[16];
		byte t,u,v;
		int i,j;
		int rdIndex =160 ;//定义roundkeys的索引,这里相当于指针的作用
		// first round
		for(i=0 ; i<AES_BLOCK_SIZE; ++i)
		{
			plaintext[i] = (byte) (ciphertext[i] ^ roundkeys[rdIndex+i]);
		}
		
		rdIndex -= 16;
		
		inv_shift_rows(plaintext);
		
		for (i = 0; i < AES_BLOCK_SIZE; ++i)
		{
			plaintext[i] = INV_SBOX[plaintext[i]&0x0FF];
		}

		for (j = 1; j < AES_ROUNDS; ++j) 
		{

			// Inverse AddRoundKey
			for (i = 0; i < AES_BLOCK_SIZE; ++i) {
				tmp[i] = (byte) (plaintext[i] ^ roundkeys[rdIndex+i]);
			}

			/*
			 * Inverse MixColumns
			 * [0e 0b 0d 09]   [s0  s4  s8  s12]
			 * [09 0e 0b 0d] . [s1  s5  s9  s13]
			 * [0d 09 0e 0b]   [s2  s6  s10 s14]
			 * [0b 0d 09 0e]   [s3  s7  s11 s15]
			 */
			for (i = 0; i < AES_BLOCK_SIZE; i += 4) {
				t = (byte) (tmp[i] ^ tmp[i + 1] ^ tmp[i + 2] ^ tmp[i + 3]);
				plaintext[i] = (byte) (t ^ tmp[i] ^ mul2((byte) (tmp[i] ^ tmp[i + 1])));
				plaintext[i + 1] = (byte) (t ^ tmp[i + 1] ^ mul2((byte) (tmp[i + 1] ^ tmp[i + 2])));
				plaintext[i + 2] = (byte) (t ^ tmp[i + 2] ^ mul2((byte) (tmp[i + 2] ^ tmp[i + 3])));
				plaintext[i + 3] = (byte) (t ^ tmp[i + 3] ^ mul2((byte) (tmp[i + 3] ^ tmp[i])));
				u = mul2(mul2((byte) (tmp[i] ^ tmp[i + 2])));
				v = mul2(mul2((byte) (tmp[i + 1] ^ tmp[i + 3])));
				t = mul2((byte) (u ^ v));
				plaintext[i] ^= t ^ u;
				plaintext[i + 1] ^= t ^ v;
				plaintext[i + 2] ^= t ^ u;
				plaintext[i + 3] ^= t ^ v;
			}

			// Inverse ShiftRows
			inv_shift_rows(plaintext);

			// Inverse SubBytes
			for (i = 0; i < AES_BLOCK_SIZE; ++i) {
				plaintext[i] = INV_SBOX[plaintext[i]&0x0FF];
			}

			rdIndex -= 16;
		}
		
		// last AddRoundKey
		for (i = 0; i < AES_BLOCK_SIZE; ++i) {
			plaintext[i] ^= roundkeys[rdIndex+i];
		}						
	}
	
	
}




    

2.2、C#中实现aes_encrypt_128

1、和C语言相比C#中也没有数组指针的概念,这里采用和Java中同样的处理方法利用数组索引解决;

2、但与Java不同C#中的byte的取值范围和C语言中unsigned char一样为0-255,不需要与0x0FF进行位与操作处理。

C#对应的代码如下:

using System;

/*
 *
 * 主要是解密、解密,10轮产生轮秘钥的函数,
 * 加密与解密函数分别调用产生轮秘钥的函数,每轮的输入与轮密钥异或一次,轮秘钥产生函数需要调用S盒函数,进行映射
 * 变量: *roundkeys存放产生轮秘钥的指针,*plaintext存放明文的指针,*ciphertext存放密文的指针,*state运行加密操作的4*4矩阵
 *
 */

namespace AES128
{
    public class AES
    {

        static int AES_BLOCK_SIZE = 16;
        static int AES_ROUNDS = 10;
        static int AES_ROUND_KEY_SIZE = 176;// AES-128 has 10 rounds, and there is a AddRoundKey before first round. (10+1)x16=176.
        /*
         * 作用:初始设置的秘钥,为16个Byte
         * 类型:一个Byte的数据
         */

        byte[] key = { 0x40, 0x41, 0x40, 0x41, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x41, 0x40, 0x41, 0x39 };

        /*
         * 作用:存放秘钥扩展后的轮秘钥,为44个字,共176Byte
         * 类型:一个Byte的数据
         */
        byte[] roundkeys = new byte[AES_ROUND_KEY_SIZE];

        /*
         * 作用:秘钥扩展中要进行异或操作的一维数组
         * 类型:静态的一个Byte的数据
         */
        static byte[] RC = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };


        /*
         * 作用:进行映射操作的S盒
         * 类型:静态的一个Byte的数据
         */
        static byte[] SBOX = {
            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盒
         * 类型:静态的一个Byte的数据
         */
        static byte[] INV_SBOX = {
            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 };





        /**
         * 功能:  由初始秘钥产生轮秘钥,将产生的轮秘钥放在*roundkeys中
         * 参数:  传入初始秘钥的地址,和轮秘钥的地址
         * 返回值:  无
         */
        void aes_key_schedule_128(byte[] key, byte[] roundkeys)
        {
            byte[] temp = new byte[4];
            int last4bytes = 12; // point to the last 4 bytes of one round
            int i;
            int index = 0;//用于循环计算

            for (i = 0; i < 16; i++)
            {
                roundkeys[index++] = key[i];
            }


            //利用索引解决C中的指针问题
            int index_l4b = 0;


            for (i = 0; i < 10; i++)
            {   //更新代替引用
                // k0-k3 for next round
                //java中的byte-127--128需要&0x0FF处理\C#中没有必要
                temp[3] = SBOX[roundkeys[last4bytes + index_l4b++]];
                temp[0] = SBOX[roundkeys[last4bytes + index_l4b++]];
                temp[1] = SBOX[roundkeys[last4bytes + index_l4b++]];
                temp[2] = SBOX[roundkeys[last4bytes + index_l4b++]];
                temp[0] ^= RC[i];

                int lastround = 16 * i;

                roundkeys[index++] = (byte)(temp[0] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(temp[1] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(temp[2] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(temp[3] ^ roundkeys[lastround++]);
                // k4-k7 for next round        
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                // k8-k11 for next round

                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                // k12-k15 for next round
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
                roundkeys[index++] = (byte)(roundkeys[last4bytes + index_l4b++] ^ roundkeys[lastround++]);
            }


        }


         /*
         * 功能:  将矩阵中的每个横列进行逆循环式移位
         * 描述:
         *  Row0: s0  s4  s8  s12   >>> 0 byte
         *  Row1: s1  s5  s9  s13   >>> 1 byte
         *  Row2: s2  s6  s10 s14   >>> 2 bytes
         *  Row3: s3  s7  s11 s15   >>> 3 bytes
         * 参数:  传入一个4*4的矩阵
         * 返回值:  无
        */
        private void inv_shift_rows(byte[] state)
        {
            byte temp;
            //row1
            temp = state[13];
            state[13] = state[9];
            state[9] = state[5];
            state[5] = state[1];
            state[1] = temp;
            //row2

            temp = state[14];
            state[14] = state[6];
            state[6] = temp;
            temp = state[10];
            state[10] = state[2];
            state[2] = temp;
            // row3
            temp = state[3];
            state[3] = state[7];
            state[7] = state[11];
            state[11] = state[15];
            state[15] = temp;
        }

        /*
	     * 功能:  加密或解密中使用的多项式(x^8 + x^4 + x^3 + x + 1 = 0)更快处理数据
	     * 不使用mul(uint8_t a, uint8_t b),而使用mul2(int8_t a)
	     * 参数:  传入要处理的一个Byte数据
	     * 返回值:  直接返回处理后的数据
        */
        private  byte mul2(byte a)
        {
            //考虑java中byte有符号
            return (byte)((a & 0x80) != 0 ? ((a << 1) ^ 0x1b) : (a << 1));
        }



        /*
         * 功能:  对密文进行解密的解密函数,将解密后的明文放在*plaintext中
         * 参数:  传入轮秘钥的地址、明文、密文的地址
         * 返回值:  无
         */

        private void aes_decrypt_128(byte[] roundkeys, byte[] ciphertext, byte[] plaintext)
        {
            byte[] tmp = new byte[16];
            byte t, u, v;
            int i, j;
            int rdIndex = 160;//定义roundkeys的索引,这里相当于指针的作用
                              // first round
            for (i = 0; i < AES_BLOCK_SIZE; ++i)
            {
                plaintext[i] = (byte)(ciphertext[i] ^ roundkeys[rdIndex + i]);
            }

            rdIndex -= 16;

            inv_shift_rows(plaintext);

            for (i = 0; i < AES_BLOCK_SIZE; ++i)
            {
                plaintext[i] = INV_SBOX[plaintext[i] & 0x0FF];
            }

            for (j = 1; j < AES_ROUNDS; ++j)
            {

                // Inverse AddRoundKey
                for (i = 0; i < AES_BLOCK_SIZE; ++i)
                {
                    tmp[i] = (byte)(plaintext[i] ^ roundkeys[rdIndex + i]);
                }

                /*
                 * Inverse MixColumns
                 * [0e 0b 0d 09]   [s0  s4  s8  s12]
                 * [09 0e 0b 0d] . [s1  s5  s9  s13]
                 * [0d 09 0e 0b]   [s2  s6  s10 s14]
                 * [0b 0d 09 0e]   [s3  s7  s11 s15]
                 */
                for (i = 0; i < AES_BLOCK_SIZE; i += 4)
                {
                    t = (byte)(tmp[i] ^ tmp[i + 1] ^ tmp[i + 2] ^ tmp[i + 3]);
                    plaintext[i] = (byte)(t ^ tmp[i] ^ mul2((byte)(tmp[i] ^ tmp[i + 1])));
                    plaintext[i + 1] = (byte)(t ^ tmp[i + 1] ^ mul2((byte)(tmp[i + 1] ^ tmp[i + 2])));
                    plaintext[i + 2] = (byte)(t ^ tmp[i + 2] ^ mul2((byte)(tmp[i + 2] ^ tmp[i + 3])));
                    plaintext[i + 3] = (byte)(t ^ tmp[i + 3] ^ mul2((byte)(tmp[i + 3] ^ tmp[i])));
                    u = mul2(mul2((byte)(tmp[i] ^ tmp[i + 2])));
                    v = mul2(mul2((byte)(tmp[i + 1] ^ tmp[i + 3])));
                    t = mul2((byte)(u ^ v));
                    plaintext[i] ^=(byte)(t ^ u);
                    plaintext[i + 1] ^= (byte)(t ^ v);
                    plaintext[i + 2] ^= (byte)(t ^ u);
                    plaintext[i + 3] ^= (byte)(t ^ v);
                }

                // Inverse ShiftRows
                inv_shift_rows(plaintext);

                // Inverse SubBytes
                for (i = 0; i < AES_BLOCK_SIZE; ++i)
                {
                    plaintext[i] = INV_SBOX[plaintext[i] & 0x0FF];
                }

                rdIndex -= 16;
            }

            // last AddRoundKey
            for (i = 0; i < AES_BLOCK_SIZE; ++i)
            {
                plaintext[i] ^= roundkeys[rdIndex + i];
            }
        }

    }
}

 


版权声明:本文为zhoudapeng01原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。