最近项目中有一个需求,实现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     F0x63, 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 roundint 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 roundroundkeys[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 roundroundkeys[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;//row1temp = state[13];state[13] = state[9];state[9] = state[5];state[5] = state[1];state[1] = temp;//row2temp = state[14];state[14] = state[6];state[6] = temp;temp = state[10];state[10] = state[2];state[2] = temp;// row3temp = 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 roundfor(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 AddRoundKeyfor (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 ShiftRowsinv_shift_rows(plaintext);// Inverse SubBytesfor (i = 0; i < AES_BLOCK_SIZE; ++i) {plaintext[i] = INV_SBOX[plaintext[i]&0x0FF];}rdIndex -= 16;}// last AddRoundKeyfor (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 roundint 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 roundroundkeys[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 roundroundkeys[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;//row1temp = state[13];state[13] = state[9];state[9] = state[5];state[5] = state[1];state[1] = temp;//row2temp = state[14];state[14] = state[6];state[6] = temp;temp = state[10];state[10] = state[2];state[2] = temp;// row3temp = 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 roundfor (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 AddRoundKeyfor (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 ShiftRowsinv_shift_rows(plaintext);// Inverse SubBytesfor (i = 0; i < AES_BLOCK_SIZE; ++i){plaintext[i] = INV_SBOX[plaintext[i] & 0x0FF];}rdIndex -= 16;}// last AddRoundKeyfor (i = 0; i < AES_BLOCK_SIZE; ++i){plaintext[i] ^= roundkeys[rdIndex + i];}}}
}

AES128加密算法的实现(C/Java/C#)相关推荐

  1. 【IoT】加密与安全:CC254x 低功耗蓝牙 BLE 之 AES-128 加密算法

    蓝牙数据是可以通过空中抓包而被抓取到的,因此需要将通信数据进行加密,即使别人截获了加密后的数据,也无法利用该数据. AES 加密原理 CC254x 支持对称加密 AES: 加密过程: 需要加密的数据 ...

  2. 低功耗蓝牙BLE之AES-128加密算法

    版权声明: 博主:枫之星雨 声明:本文为博主原创文章,转载请注明原文出处. 博文地址:点击进入 邮箱:454086991@qq.com QQ号:454086991(申请加好友时请备注"技术交 ...

  3. AES128加密算法与实现1

    c语言实现的aes加密算法,可对128位数据进行一次加密.具体实现方法如下,调用示例可参照本文最后部分.我还有aes128加密算法的flash演示视频,需要详细了解该加密算法的朋友,可以联系我索取. ...

  4. AES128加密算法实现(C语言:ECB加密模式实现)

    AES简介 高级加密标准AES(Advanced Encryption Standard)是一种常见的对称加密算法. 详细介绍如下链接: https://blog.csdn.net/qq_282051 ...

  5. RSA - 非对称加密算法简要介绍与JAVA实现

    [1]RSA简介 RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年 ...

  6. AES128加密算法完整实现

    概述 原本想把自己AES加密算法的整个实现过程给详细复述下来,分享给想学习的同学,也方便自己复习,但后来发现该工作量太大,加上作业太多没有过多的时间去写.所以就想把自己在学习的过程中多遇到的好的文章进 ...

  7. 即时通讯学习笔记006---认识学习OpenFire服务器用的加密算法Blowfish_以及用java实现Blowfish算法

    这个算法: 有个在线工具,可以进行加密解密 http://tool.chacuo.net/cryptblowfish 个人认为目前比较安全的加密算法:Blowfish. 上代码之前,先说几点Blowf ...

  8. AES-128 加密算法

    转自http://blog.sina.com.cn/s/blog_60cf051301015orf.html 在网上找了一大堆资料,总有把AES加密有点弄懂了.这里推荐一个人写的博客.再次非常感谢这位 ...

  9. playfair密码和凯撒密码加密算法的Java实现

    文章目录 一.实现广义的凯撒密码加密算法 二.实现广义的playfair密码的加密算法 总结 加密原理: 一.实现广义的凯撒密码加密算法 //实现广义的凯撒密码//凯撒密码的加密String plai ...

最新文章

  1. mysql和java区别_java和mysql的length()区别及char_length()
  2. Keil编译产生的RO,RW和ZI是什么
  3. 成功解决 编程语言代码结果中输出-9223372036854775808的数据
  4. Java 读写 hdfs文件或者目录
  5. 学习STM32很简单?
  6. 服务端负载均衡和客户端负载均衡
  7. Windows Phone 8.1 多媒体(3):音乐
  8. 几乎是苹果6倍!华为可穿戴设备出货量Q1同比猛增282%
  9. CAS的ABA问题及解决方案
  10. 如何显示计算机窗口的状态栏,如何让电脑任务栏不显示打开的程序或窗口方法...
  11. 代码实现-pack_padded_sequence()与pad_packed_sequence()
  12. 【应急类漏洞】Linux下变种DDG挖矿病毒紧急通告及处置方法
  13. Outlook 2013 重新联姻Hotmail ,Exchange ActiveSync牵线搭桥
  14. 电商小程序实战教程-需求分析
  15. 案例分享 | 数字化综合人才管理平台
  16. 数据方舟插件_数据方舟 for Excel工具箱使用说明
  17. 诚之和:谁在疯狂制造小红书的“打卡地”?
  18. 常用的json处理工具类
  19. 真假蜘蛛识别php,两招教你轻松识别百度真假蜘蛛(实操教程)
  20. 浅谈:传统制造企业数字化转型常见问题及解决方案

热门文章

  1. 想开发一套多人交友app必须知道的
  2. 扩展log4j2日志归档功能预研
  3. C语言简单教程一:编程的第一课
  4. 「SQL面试题库」 No_55 销售分析 I
  5. android 11.0 12.0设置app为默认浏览器
  6. 树美滑块验证——滑块识别、获取和提交参数一条龙分析和调用
  7. 全美航班停飞原因曝光/ 米哈游辟谣年终奖108薪/ 苹果正开发触摸屏Mac…今日更多新鲜事在此...
  8. 浏览器(网页浏览器)
  9. Altium Designer软件导出原理图和PCB图的PDF形式
  10. 阿里、京东、百度“激战”互联网医疗