AES加密解密算法的Java实现

本文详细介绍了如何使用Java实现AES算法,并通过示例展示了加密与解密的过程。主要内容包括算法类的实现、密钥扩展、字节操作等关键步骤。

工作需要,花了两个下午将Aes算法了解了一下并用java实现了一遍(此处借鉴了老外的C#的实现),本人非信息安全专业和软件,代码还有漏洞,欢迎指出~~~

先贴上代码:

=================================================AES.java主要的类实现====================================================

package aesHelper.Aes;

/**
 * AES字节数组加密算法类
 * 
 * @author DC 2011/11/5
 */
public class Aes
{
	/*************************** 成员变量 ************************************/

	private int Nb;// 以32位为单位的字长
	private int Nk;// 以32位为单位的密钥长度
	private int Nr;// 轮数
	private byte[] key;// 密钥
	private byte[][] Sbox;// S盒矩阵
	private byte[][] iSbox;// s盒逆矩阵
	private byte[][] w;// 密钥调度表
	private byte[][] Rcon;// 轮常数表
	private byte[][] State;// 状态矩阵

	/**
	 * 构造方法
	 * 
	 * @param keySize
	 * @param keyBytes
	 */
	public Aes(int keySize, byte[] keyBytes, int Nb)
	{
		SetNbNkNr(keySize, Nb);
		this.key = new byte[this.Nk * 4];
		this.key = keyBytes;

		BuildSbox();
		BuildInvSbox();
		BuildRcon();
		KeyExpansion();
	}

	/*************************** 私有方法 ************************************/

	/**
	 * 生成Rcon轮常数矩阵
	 */
	private void BuildRcon()
	{
		// 0x00,0x01,0x02,0x04,
		// 0x08,0x10,0x20,0x40,
		// 0x80,0x1b,0x36,0x6c,
		// 0xd8,0xab,0x4d,0x9a,
		// 0x2f,0x5e,0xbc,0x63,
		// 0xc6,0x97,0x35,0x6a,
		// 0xd4,0xb3,0x7d,0xfa,
		// 0xef,0xc5,0x91,0x39};
		this.Rcon = new byte[100][4];
		Rcon[0][0]=0x00;//Rcon[1][0]=0x01;		
		for(int i=1;i<100;i++)
		{
			Rcon[i][0]=gfmultby02(Rcon[i-1][0]);
		}
	}

	/**
	 * 设置Nb,Nk,Nr
	 * 
	 * @param keysize
	 */
	private void SetNbNkNr(int keysize, int Nb)
	{
		this.Nb = Nb;
		switch (keysize)
		{
		case KEYSIZE.Bit128:
			this.Nk = 4;
			this.Nr = 10;
			break;
		case KEYSIZE.Bit192:
			this.Nk = 6;
			this.Nr = 12;
			break;
		case KEYSIZE.Bit256:
			this.Nk = 8;
			this.Nr = 14;
			break;
		}
	}

	/**
	 * 生成S盒矩阵
	 */
	private void BuildSbox()
	{
		this.Sbox = new byte[][] {
				/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
				/* 0 */{ 0x63, 0x7c, 0x77, 0x7b, (byte) 0xf2, 0x6b, 0x6f,
						(byte) 0xc5, 0x30, 0x01, 0x67, 0x2b, (byte) 0xfe,
						(byte) 0xd7, (byte) 0xab, 0x76 },
				/* 1 */{ (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 },
				/* 2 */{ (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 },
				/* 3 */{ 0x04, (byte) 0xc7, 0x23, (byte) 0xc3, 0x18,
						(byte) 0x96, 0x05, (byte) 0x9a, 0x07, 0x12,
						(byte) 0x80, (byte) 0xe2, (byte) 0xeb, 0x27,
						(byte) 0xb2, 0x75 },
				/* 4 */{ 0x09, (byte) 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a,
						(byte) 0xa0, 0x52, 0x3b, (byte) 0xd6, (byte) 0xb3,
						0x29, (byte) 0xe3, 0x2f, (byte) 0x84 },
				/* 5 */{ 0x53, (byte) 0xd1, 0x00, (byte) 0xed, 0x20,
						(byte) 0xfc, (byte) 0xb1, 0x5b, 0x6a, (byte) 0xcb,
						(byte) 0xbe, 0x39, 0x4a, 0x4c, 0x58, (byte) 0xcf },
				/* 6 */{ (byte) 0xd0, (byte) 0xef, (byte) 0xaa, (byte) 0xfb,
						0x43, 0x4d, 0x33, (byte) 0x85, 0x45, (byte) 0xf9, 0x02,
						0x7f, 0x50, 0x3c, (byte) 0x9f, (byte) 0xa8 },
				/* 7 */{ 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 },
				/* 8 */{ (byte) 0xcd, 0x0c, 0x13, (byte) 0xec, 0x5f,
						(byte) 0x97, 0x44, 0x17, (byte) 0xc4, (byte) 0xa7,
						0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 },
				/* 9 */{ 0x60, (byte) 0x81, 0x4f, (byte) 0xdc, 0x22, 0x2a,
						(byte) 0x90, (byte) 0x88, 0x46, (byte) 0xee,
						(byte) 0xb8, 0x14, (byte) 0xde, 0x5e, 0x0b, (byte) 0xdb },
				/* a */{ (byte) 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
						(byte) 0xc2, (byte) 0xd3, (byte) 0xac, 0x62,
						(byte) 0x91, (byte) 0x95, (byte) 0xe4, 0x79 },
				/* b */{ (byte) 0xe7, (byte) 0xc8, 0x37, 0x6d, (byte) 0x8d,
						(byte) 0xd5, 0x4e, (byte) 0xa9, 0x6c, 0x56,
						(byte) 0xf4, (byte) 0xea, 0x65, 0x7a, (byte) 0xae, 0x08 },
				/* c */{ (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 },
				/* d */{ 0x70, 0x3e, (byte) 0xb5, 0x66, 0x48, 0x03,
						(byte) 0xf6, 0x0e, 0x61, 0x35, 0x57, (byte) 0xb9,
						(byte) 0x86, (byte) 0xc1, 0x1d, (byte) 0x9e },
				/* e */{ (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 },
				/* f */{ (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盒矩阵
	 */
	private void BuildInvSbox()
	{
		// this.Sbox = new byte[][] {};
		// 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,

		int x, y;
		this.iSbox = new byte[16][16];
		for (int i = 0; i < 16; i++)
		{
			// System.out.println("i="+i);
			for (int j = 0; j < 16; j++)
			{
				x = (int) ((this.Sbox[i][j] >> 4) & 0x0f);
				y = (int) (this.Sbox[i][j] & 0x0f);
				// System.out.println("x="+x+" y="+y);
				this.iSbox[x][y] = (byte) (16 * i + j);
			}
		}
	}

	/**
	 * 扩展密钥
	 */
	private void KeyExpansion()
	{
		this.w = new byte[Nb * (Nr + 1)][4];

		for (int row = 0; row < Nk; ++row)
		{
			this.w[row][0] = this.key[4 * row];
			this.w[row][1] = this.key[4 * row + 1];
			this.w[row][2] = this.key[4 * row + 2];
			this.w[row][3] = this.key[4 * row + 3];
		}

		byte[] temp = new byte[Nb];

		for (int row = Nk; row < Nb * (Nr + 1); ++row)
		{
			temp[0] = this.w[row - 1][0];
			temp[1] = this.w[row - 1][1];
			temp[2] = this.w[row - 1][2];
			temp[3] = this.w[row - 1][3];

			if (row % Nk == 0)
			{
				temp = SubWord(RotWord(temp));
				temp[0] = (byte) (temp[0] ^ this.Rcon[row / Nk][0]);
				temp[1] = (byte) (temp[1] ^ this.Rcon[row / Nk][1]);
				temp[2] = (byte) (temp[2] ^ this.Rcon[row / Nk][2]);
				temp[3] = (byte) (temp[3] ^ this.Rcon[row / Nk][3]);
			} else if (Nk > 6 && (row % Nk == 4))
			{
				temp = SubWord(temp);
			}

			this.w[row][0] = (byte) (this.w[row - Nk][0] ^ temp[0]);
			this.w[row][1] = (byte) (this.w[row - Nk][1] ^ temp[1]);
			this.w[row][2] = (byte) (this.w[row - Nk][2] ^ temp[2]);
			this.w[row][3] = (byte) (this.w[row - Nk][3] ^ temp[3]);
		}
	}

	/**
	 * SubWord方法
	 * 
	 * @param subWord
	 * @return
	 */
	private byte[] SubWord(byte[] subWord)
	{
		for (int c = 0; c < subWord.length; ++c)
		{
			subWord[c] = this.Sbox[(subWord[c] >> 4) & 0x0f][(subWord[c] & 0x0f)];
		}
		return subWord;
	}

	/**
	 * RotWord方法
	 * 
	 * @param rotWord
	 * @return
	 */
	private byte[] RotWord(byte[] rotWord)
	{
		byte[] temp = rotWord;
		byte[] b = new byte[4];
		for (int i = 0; i < 4; i++)
		{
			b[i] = temp[(i + 1) % 4];
		}
		return b;
	}

	/**
	 * 轮密钥加
	 * 
	 * @param round
	 */
	private void AddRoundKey(int round)
	{
		for (int r = 0; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				this.State[r][c] = (byte) (this.State[r][c] ^ w[(round * Nb)
						+ c][r]);
			}
		}
	}

	/**
	 * SubBytes方法
	 */
	private void SubBytes()
	{

		for (int r = 0; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				this.State[r][c] = this.Sbox[(this.State[r][c] >> 4) & 0x0f][(this.State[r][c] & 0x0f)];
			}
		}
	}

	/**
	 * InvSubBytes方法
	 */
	private void InvSubBytes()
	{
		for (int r = 0; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				this.State[r][c] = this.iSbox[(this.State[r][c] >> 4) & 0x0f][(this.State[r][c] & 0x0f)];
			}
		}
	}

	/**
	 * 行移位
	 */
	private void ShiftRows()
	{
		byte[][] temp = new byte[4][Nb];
		for (int r = 0; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				temp[r][c] = this.State[r][c];
			}
		}
		for (int r = 1; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				this.State[r][c] = temp[r][(c + r) % Nb];
			}
		}

		// System.out.println();
		// for (int r = 0; r < 4; r++)
		// {
		// for (int c = 0; c < 4; c++)
		// {
		// System.out.print(State[r][c]+" ");
		// }
		// System.out.println();
		// }
		//		
	}

	/**
	 * 逆行移位
	 */
	private void InvShiftRows()
	{
		byte[][] temp = new byte[4][Nb];
		for (int r = 0; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				temp[r][c] = this.State[r][c];
			}
		}

		for (int r = 1; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				this.State[r][c] = temp[r][(c - r + Nb) % Nb];
			}
		}

		// System.out.println();
		// for (int r = 0; r < 4; ++r)
		// {
		// for (int c = 0; c < 4; ++c)
		// {
		// System.out.print(this.State[r][c] + " ");
		// }
		// System.out.println();
		// }

	}

	/**
	 * 列混合
	 */
	private void MixColumns()
	{
		byte[][] temp = new byte[4][Nb];
		for (int r = 0; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				temp[r][c] = this.State[r][c];
			}
		}

		for (int c = 0; c < Nb; ++c)
		{
			this.State[0][c] = (byte) (gfmultby02(temp[0][c])
					^ gfmultby03(temp[1][c]) ^ gfmultby01(temp[2][c]) ^ gfmultby01(temp[3][c]));
			this.State[1][c] = (byte) (gfmultby01(temp[0][c])
					^ gfmultby02(temp[1][c]) ^ gfmultby03(temp[2][c]) ^ gfmultby01(temp[3][c]));
			this.State[2][c] = (byte) (gfmultby01(temp[0][c]) ^ (gfmultby01(temp[1][c])
					^ gfmultby02(temp[2][c]) ^ gfmultby03(temp[3][c])));
			this.State[3][c] = (byte) (gfmultby03(temp[0][c])
					^ gfmultby01(temp[1][c]) ^ (gfmultby01(temp[2][c]) ^ gfmultby02(temp[3][c])));
		}
	}

	/**
	 * 逆列混合
	 */
	private void InvMixColumns()
	{
		byte[][] temp = new byte[4][Nb];
		for (int r = 0; r < 4; ++r)
		{
			for (int c = 0; c < Nb; ++c)
			{
				temp[r][c] = this.State[r][c];
			}
		}

		for (int c = 0; c < Nb; c++)
		{
			this.State[0][c] = (byte) (gfmultby0e(temp[0][c])
					^ gfmultby0b(temp[1][c]) ^ gfmultby0d(temp[2][c]) ^ gfmultby09(temp[3][c]));
			this.State[1][c] = (byte) (gfmultby09(temp[0][c])
					^ gfmultby0e(temp[1][c]) ^ gfmultby0b(temp[2][c]) ^ gfmultby0d(temp[3][c]));
			this.State[2][c] = (byte) (gfmultby0d(temp[0][c]) ^ (gfmultby09(temp[1][c])
					^ gfmultby0e(temp[2][c]) ^ gfmultby0b(temp[3][c])));
			this.State[3][c] = (byte) (gfmultby0b(temp[0][c])
					^ gfmultby0d(temp[1][c]) ^ (gfmultby09(temp[2][c]) ^ gfmultby0e(temp[3][c])));
		}
	}

	// 有限域GF(28)部分变换
	private byte gfmultby01(byte b)
	{
		return b;
	}

	private byte gfmultby02(byte b)
	{
		// if (b < 0x80 && b >= 0) // !!!!!!!这里比较大小的时候注意符号位
		// return (byte) (b << 1);
		// else
		// return (byte) ((b << 1) ^ (byte) 0x1b);
		if (((b >> 7) & 0x01) == 0) // !!!!!!!这里比较大小的时候注意符号位
			return (byte) (b << 1);
		else
			return (byte) ((b << 1) ^ (byte) 0x1b);
		// 消除符号位可以用b&0xff
	}

	private byte gfmultby03(byte b)
	{
		return (byte) (gfmultby02(b) ^ gfmultby01(b));
	}

	private byte gfmultby09(byte b)
	{
		return (byte) (gfmultby02(gfmultby02(gfmultby02(b))) ^ gfmultby01(b));
	}

	private byte gfmultby0b(byte b)
	{
		return (byte) (gfmultby02(gfmultby02(gfmultby02(b))) ^ gfmultby02(b) ^ gfmultby01(b));
	}

	private byte gfmultby0d(byte b)
	{
		return (byte) (gfmultby02(gfmultby02(gfmultby02(b)))
				^ gfmultby02(gfmultby02(b)) ^ gfmultby01(b));
	}

	private byte gfmultby0e(byte b)
	{
		return (byte) (gfmultby02(gfmultby02(gfmultby02(b)))
				^ gfmultby02(gfmultby02(b)) ^ gfmultby02(b));
	}

	/*************************** 公有方法 ************************************/

	/**
	 * 加密过程
	 * 
	 * @param input
	 * @param output
	 */
	public void Cipher(byte[] input, byte[] output)
	{
		this.State = new byte[4][Nb];
		for (int i = 0; i < (4 * Nb); i++)
		{
			this.State[i / Nb][i % Nb] = input[i];
		}// 初始化状态矩阵
		AddRoundKey(0);// 轮密钥加
		for (int round = 1; round < Nr; ++round)
		{
			SubBytes();// S盒变换
			ShiftRows();// 行移位
			MixColumns();// 列混合
			AddRoundKey(round);
		}
		SubBytes();// S盒置换
		ShiftRows();// 行移位
		AddRoundKey(Nr);// 轮密钥加
		for (int i = 0; i < (4 * Nb); i++)
		{
			output[i] = this.State[i / Nb][i % Nb];
			// System.out.println((i%Nb));
		}// 输出密文
	}

	public void Cipher(String input, String output)
	{

	}

	/**
	 * 解密过程
	 * 
	 * @param inputs
	 * @param output
	 */
	public void Invcipher(byte[] input, byte[] output)
	{
		this.State = new byte[4][Nb];
		for (int i = 0; i < (4 * Nb); ++i)
		{
			this.State[i / Nb][i % Nb] = input[i];
		}// 初始化状态矩阵
		AddRoundKey(Nr);// 轮密钥加
		for (int round = Nr - 1; round > 0; round--)
		{
			InvShiftRows();// 逆行移位
			InvSubBytes();// 逆S盒置换
			AddRoundKey(round);// 轮密钥加
			InvMixColumns();// 逆列混合
		}
		InvShiftRows();// 逆行移位
		InvSubBytes();// 逆S盒置换
		AddRoundKey(0);// 轮密钥加
		for (int i = 0; i < (4 * Nb); ++i)
		{
			output[i] = this.State[i / Nb][i % Nb];
		}// 输出结果
	}

}
=====================================================AesCipherAndInvCipher.java=====================================================
package aesHelper.Aes;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;

/**
 * 辅助类 处理明文字符输入字节数不匹配等问题
 * 
 * @author DC
 * 
 */
public class AesCipherAndInvCipher
{
	private byte[] key;// 密钥
	private byte[] pt;// 明文字节数组
	private byte[] ct;
	private int mode;
	private int Nb = 0;
	private int dataLength;
	private int blockSize = 4;// 分组大小32位,4bytes

	public AesCipherAndInvCipher(byte[] kb)
	{
		this.key=kb;
	}
	
	
	/**
	 * 加密
	 * 
	 * @param kb
	 * @param plainText
	 * @return 加密后密文字节数组
	 */
	
	private byte[] Eecrypt(String plainText, byte[] kb) throws InvalidKeyException
	{
		try
		{
			pt = plainText.getBytes("UTF-8");// 获取明文字节数组
			//System.out.println("明文字节数组:");
			//DisplayAsBytes(pt);
		} catch (UnsupportedEncodingException e)
		{
			System.out.println("不支持的编码类型!");
			e.printStackTrace();
		}
		dataLength = pt.length;
		// System.out.println(dataLength);
		mode = dataLength % blockSize;// 判断明文数组长度是否与分组长度匹配
		ct = new byte[mode == 0 ? pt.length : dataLength / blockSize * 4 + 32];// 密文字节数组
		Nb = dataLength / blockSize;
		// System.out.println(ct.length);
		Aes a1 = new Aes(KEYSIZE.Bit192, kb, Nb);
		Aes a2 = new Aes(KEYSIZE.Bit192, kb, 4);
		Aes a3 = new Aes(KEYSIZE.Bit192, kb, 4);
		if (mode == 0)
		{
			a1.Cipher(pt, ct);
		} else
		{
			//System.out.println("长度不匹配");
			byte[] b1 = new byte[blockSize * Nb];// 匹配的部分
			//System.out.println(blockSize * Nb);
			byte[] b2 = new byte[16];// 剩余部分
			byte[] b3 = new byte[16];// 存明文长度
			byte[] c1 = new byte[b1.length];
			byte[] c2 = new byte[b2.length];
			byte[] c3 = new byte[b3.length];
			System.arraycopy(pt, 0, b1, 0, b1.length);
			// System.out.println("匹配明文字节数组:");
			// DisplayAsBytes(b1);
			System.arraycopy(pt, Nb * blockSize, b2, 0, mode);
			b3 = intToByteArray(dataLength);
			// System.out.println(ct.length);			 
			a1.Cipher(b1, c1);
			 //System.out.println("c1:");
			//DisplayAsBytes(c1);
			// DisplayAsBytes(b3);
			a2.Cipher(b2, c2);
			a3.Cipher(b3, c3);
			System.arraycopy(c1, 0, ct, 0, c1.length);
			System.arraycopy(c2, 0, ct, b1.length, c2.length);
			System.arraycopy(c3, 0, ct, b1.length + b2.length, c3.length);
		}

		return ct;
	}
	
	public byte[] EecryptToBytes(String plainText, byte[] kb) throws InvalidKeyException
	{		
		byte[] ct=Eecrypt(plainText,kb);		
		return ct;
	}

	public String EecryptToString(String plainText, byte[] kb) throws InvalidKeyException
	{		
		byte[] ct = Eecrypt(plainText,kb);		
		//System.out.println("密文:"+BytesToString(ct));
		return BytesToString(ct);
		
	}
	
	/**
	 * 解密
	 */
	public String Decrypt(byte[] ct,byte[] kb)
	{
		String s="";
		if (mode == 0)
		{
			byte[] output = new byte[dataLength];
			Aes a = new Aes(KEYSIZE.Bit192, kb, Nb);
			a.Invcipher(ct, output);			
			try
			{
				s = new String(output, "UTF-8");
				System.out.println("解密:" + s);
			} catch (UnsupportedEncodingException e)
			{
				System.out.println("不支持的编码格式!");
				e.printStackTrace();
			}
		} else
		{
			byte[] length = new byte[16];
			byte[] plainText1 = new byte[ct.length - 32];
			byte[] plainText2 = new byte[16];
			Aes a1 = new Aes(KEYSIZE.Bit192, kb, Nb);
			Aes a2 = new Aes(KEYSIZE.Bit192, kb, 4);
			Aes a3 = new Aes(KEYSIZE.Bit192, kb, 4);
			byte[] c1 = new byte[ct.length - 32];
			byte[] c2 = new byte[16];
			byte[] c3 = new byte[16];
			System.arraycopy(ct, ct.length - 16, c3, 0, c3.length);
			System.arraycopy(ct, ct.length - 32, c2, 0, c2.length);
			System.arraycopy(ct, 0, c1, 0, Nb * blockSize);
			//System.out.println("密文匹配部分c1:");
			//DisplayAsBytes(c1);
			a3.Invcipher(c3, length);// 解密明文字节数组长度
			a2.Invcipher(c2, plainText2);// 解密剩余的部分
			a1.Invcipher(c1, plainText1);// 解密匹配的部分
			// System.out.println(plainText1.length);
			//System.out.println("解密后字节数组长度:");
			//DisplayAsBytes(length);
			//System.out.println("解密后匹配部分:");
			//DisplayAsBytes(plainText1);
			//System.out.println("解密后剩余部分:");
			//DisplayAsBytes(plainText2);
			// DisplayAsBytes(output);
			// int length;
			int length1 = byteArrayToInt(length);
			//System.out.println("\n解密长度后:" + length1);
			byte[] output = new byte[length1];
			System.arraycopy(plainText1, 0, output, 0, plainText1.length);
			System.arraycopy(plainText2, 0, output, plainText1.length, length1
					- plainText1.length);
			//System.out.println("解密后字节数组:");
			//DisplayAsBytes(output);			
			try
			{
				s = new String(output, "UTF-8");
				System.out.println("解密后明文:" + s);
			} catch (UnsupportedEncodingException e)
			{
				System.out.println("不支持的编码格式!");
				e.printStackTrace();
			}
		}
		return s;
	}

	public String Decrypt(String cryptText,byte[] kb)
	{
		//System.out.println(cryptText+" "+cryptText.length());
		byte[] ct=StringToBytes(cryptText);	
		//DisplayAsBytes(ct);
		return Decrypt(ct,kb);
	}
	
	public String Decrypt(Byte[] ct,byte[] kb)
	{	
		return Decrypt(ct,kb);
	}
	
	/**
	 * int转化为Byte数组
	 * 
	 * @param value
	 * @return
	 */
	private static byte[] intToByteArray(int value)
	{
		byte[] b = new byte[16];
		for (int i = 0; i < 4; i++)
		{
			int offset = (b.length - 1 - i) * 8;
			b[i] = (byte) ((value >>> offset) & 0xFF);
		}
		for (int i = 4; i < 16; i++)
		{
			b[i] = 0;
		}
		return b;
	}

	/**
	 * byte数组转化为int
	 * 
	 * @param b
	 * @return
	 */
	private static final int byteArrayToInt(byte[] b)
	{
		byte[] b1 = new byte[4];
		System.arraycopy(b, 0, b1, 0, 4);
		//DisplayAsBytes(b1);
		//System.out.println(b1[0] << 24);
		return (b1[0] << 24) + ((b1[1] & 0xFF) << 16) + ((b1[2] & 0xFF) << 8)
				+ (b1[3] & 0xFF);

		// targets[0] = (byte) (res & 0xff);// 最低位
		// targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
		// targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
		// targets[3] = (byte) (res >>> 24);// 最高位,无符号右移。
		// return targets;
	}

	/**
	 * 显示字节数组
	 * 
	 * @param b
	 */
	private static void DisplayAsBytes(byte[] b)
	{
		for (int i = 0; i < b.length; i++)
		{
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1)
			{
				hex = '0' + hex;
			}
			System.out.print(hex.toUpperCase() + " ");
		}
		System.out.println();
	}
	
	private static String BytesToString(byte[] b)
	{
		String s = "";
		for (int i = 0; i < b.length; i++)
		{
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1)
			{
				hex = '0' + hex;
			}
			s+=hex;
		}
		return s;
	}
	
	private static byte[] StringToBytes(String cryptText)
	{
		byte[] b=new byte[cryptText.length()/2];
		int[] a=new int[cryptText.length()];
		for(int i=0;i<cryptText.length();++i)
		{
			String s=cryptText.substring(i, i+1);
			//System.out.print(i);
			if(s.equals("a"))			
				a[i]=10;
			else if(s.equals("b"))
				a[i]=11;
			else if(s.equals("c"))
				a[i]=12;
			else if(s.equals("d"))
				a[i]=13;
			else if(s.equals("e"))
				a[i]=14;
			else if(s.equals("f"))
				a[i]=15;
			else
				a[i]=Integer.valueOf(s);
			
		}
		for(int i=0;i<cryptText.length()/2;i++)
		{
			b[i]=(byte) (a[2*i]*16+a[2*i+1]);
		}
		return b;
	}
	
}

======================================================generateKey.java================================================
package aesHelper.Aes;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.util.Random;

public class generateKey
{
	private static byte[] key;
	/**
	 * 随机生成key
	 * @param keySize
	 * @return
	 * @throws InvalidKeyException
	 */
	public static byte[] generateRandomKey(int keySize) throws InvalidKeyException
	{
		if (keySize == KEYSIZE.Bit128 | keySize == KEYSIZE.Bit192
				| keySize == KEYSIZE.Bit256)
		{
			key = new byte[keySize / 8];
			for (int i = 0; i < keySize / 8; i++)
			{
				Random r = new Random();
				int tempByte = r.nextInt() * 255;
				key[i] = (byte) tempByte;
			}
			// DisplayAsBytes(key);
			return key;
		} else
		{
			throw new InvalidKeyException("密钥长度错误,正确长度为128,192或者256位!");
		}

	}

	/**
	 * 根据字符串生成key
	 * @param keyStr
	 * @return
	 */
	public static byte[] generateKeyFromString(String keyStr)
	{
		byte[] tempkey=null;		
		try
		{
			tempkey = keyStr.getBytes("UTF-8");
		} catch (UnsupportedEncodingException e)
		{
			System.out.println("不支持的编码类型!");
			e.printStackTrace();
		}	
		//System.out.println("\n密钥字节数组:" + key);
		if(tempkey.length<128)
		{
			key=new byte[16];
			byte lastByte=tempkey[tempkey.length-1];
			for(int i=tempkey.length;i<16;i++)
			{
				key[i]=gfmultby02(lastByte);
				lastByte=key[i-1];
			}
			//DisplayAsBytes(key);
		}
		else if(tempkey.length>128&&tempkey.length<192)
		{
			key=new byte[24];
			byte lastByte=tempkey[tempkey.length-1];
			for(int i=tempkey.length;i<24;i++)
			{
				key[i]=gfmultby02(lastByte);
				lastByte=key[i-1];
			}
			//DisplayAsBytes(key);
		}
		else if(tempkey.length>192&&tempkey.length<256)
		{
			key=new byte[32];
			byte lastByte=tempkey[tempkey.length-1];
			for(int i=tempkey.length;i<32;i++)
			{
				key[i]=gfmultby02(lastByte);
				lastByte=key[i-1];
			}
			//DisplayAsBytes(key);
		}
		else if(tempkey.length>256)
		{
			key=new byte[32];
			System.arraycopy(tempkey, 0, key, 0, 32);
		}
		else
		{
			key=tempkey;
		}		
		return key;
		
	}

	
	public int getKeyLength()
	{
		return key.length;
	}
	private static byte gfmultby02(byte b)
	{
		// if (b < 0x80 && b >= 0) // !!!!!!!这里比较大小的时候注意符号位
		// return (byte) (b << 1);
		// else
		// return (byte) ((b << 1) ^ (byte) 0x1b);
		if (((b >> 7) & 0x01) == 0) // !!!!!!!这里比较大小的时候注意符号位
			return (byte) (b << 1);
		else
			return (byte) ((b << 1) ^ (byte) 0x1b);
		// 消除符号位可以用b&0xff
	}

	
	// public static void DisplayAsBytes(byte[] b)
	// {
	// for (int i = 0; i < b.length; i++)
	// {
	// String hex = Integer.toHexString(b[i] & 0xFF);
	// if (hex.length() == 1)
	// {
	// hex = '0' + hex;
	// }
	// System.out.print(hex.toUpperCase() + " ");
	// }
	// System.out.println();
	// }
}

====================================================KEYSIZE.java=================================================
package aesHelper.Aes;

/**
 * 密钥长度
 * 
 * @author DC
 */
public class KEYSIZE
{
	public static final int Bit128 = 128;//128位
	public static final int Bit192 = 192;//192位
	public static final int Bit256 = 256;//256位

}

===============================================以下是代码测试部分========================================================
package aesHelper.Aes;

import java.security.InvalidKeyException;

/**
 * AES算法测试
 * 
 * @author DC
 * 
 */
public class testAes
{
	public static void main(String[] args)
	{
		// *************************加密*******************************************
		byte[] plainText = new byte[] { 0x11, 0x11, 0x22, 0x33, 0x44, 0x55,
				0x66, 0x77, (byte) 0x88, (byte) 0x99, (byte) 0xaa, (byte) 0xbb,
				(byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff, 0x00, 0x11,// 0x22,
				// 0x33,0x44,
				// 0x55,
				0x66, 0x77 };// 明文
		byte[] cipherText = new byte[20];
		byte[] decipheredText = new byte[20];
		byte[] keyBytes = null;
		try
		{
			keyBytes = generateKey.generateKeyFromString("段聪wrwe2432v112wwwwwwwwwwwwwwwwwwww@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@wwwwwwwwwwwwwwwwwwwwwww34@#%$1234fffffffffffffffffffffff");
		} catch (Exception e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		// byte[] keyBytes = new byte[] { 0x23, 0x56, 0x02, 0x03, 0x04, 0x05,
		// 0x06, 0x07, 0x08, 0x09, 0x0c, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
		// 0x10, 0x11, 0x12, 0x13, 0x14, 0x51, 0x16, 0x17 };// 密钥

		Aes a = new Aes(KEYSIZE.Bit192, keyBytes, 5);
		// System.out.println("AES加密算法");
		// System.out.println("明文: ");
		// DisplayAsBytes(plainText);
		// System.out.println("\n使用 " + KEYSIZE.Bit192 + "位的密钥: ");
		// DisplayAsBytes(keyBytes);
		// a.Cipher(plainText, cipherText);
		// System.out.println("\n加密后的密文为: ");
		// DisplayAsBytes(cipherText);

		// String plainText1="dc";
		// String cipherText1=null;
		// Aes a = new Aes(KeySize.Bit192, keyBytes);
		// System.out.println("AES加密算法");
		// System.out.println("明文: ");
		// System.out.println(plainText1);
		// a.Cipher(plainText1, cipherText1);
		// System.out.println("\n加密后的密文为: ");
		// System.out.println(cipherText1);

		// **************************解密*******************************************
		// a.Invcipher(cipherText, decipheredText);
		// System.out.println("\n解密出结果为: ");
		// DisplayAsBytes(decipheredText);
		// System.out.println("\n完成!");

		System.out.println("***********************测试1****************************");

		byte[] key1 = null;
		try
		{
			key1 = generateKey.generateRandomKey(KEYSIZE.Bit192);
		} catch (InvalidKeyException e1)
		{
			e1.printStackTrace();
		}
		AesCipherAndInvCipher aes = new AesCipherAndInvCipher(key1);
		byte[] dt = null;
		String ss = null;
		try
		{
			dt = new byte[16];
			dt = aes.EecryptToBytes("段聪wrwe2432v1343", keyBytes);
			ss = aes.EecryptToString("段聪wrwe2432v1343", keyBytes);			
			System.out.println("明文:段聪wrwe2432v1343");
		} catch (InvalidKeyException e)
		{
			e.printStackTrace();
		}		
		aes.Decrypt(dt, keyBytes);
		aes.Decrypt(ss, keyBytes);

		System.out.println("*************************测试2*****************************");
		AesCipherAndInvCipher aes1 = new AesCipherAndInvCipher(key1);
		byte[] dt1 = null;
		try
		{
			// dt = new byte[16];
			String plainText1 = "uuid=FSFASW24S-0342-FEW3-3F33-F44F2SE523432D";
			dt1 = aes1.EecryptToBytes(plainText1, keyBytes);
			System.out.println("明文:" + plainText1);
		} catch (InvalidKeyException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//System.out.println("加密后字节数组:");
		//DisplayAsBytes(dt1);// 加密后字节数组
		aes1.Decrypt(dt1, keyBytes);

		// generateKey.generateRandomKey("dc");
	}

	/**
	 * 显示16进制
	 * 
	 * @param b
	 */
	public static void DisplayAsBytes(byte[] b)
	{
		for (int i = 0; i < b.length; i++)
		{
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1)
			{
				hex = '0' + hex;
			}
			System.out.print(hex.toUpperCase() + " ");
		}
		System.out.println();
	}
}


附录:

打包成AesHelper.jar后,可以进行以下调用:

System.out.println("******************************************************");
		byte[] key1 = null;
		try
		{
			key1 = generateKey.generateRandomKey(KEYSIZE.Bit192);
		} catch (InvalidKeyException e1)
		{
			e1.printStackTrace();
		}
		AesCipherAndInvCipher aes = new AesCipherAndInvCipher(key1);
		byte[] dt = null;
		String ss = null;
		try
		{
			dt = new byte[16];
			dt = aes.EecryptToBytes("段聪wrwe2432v!!1343", key1);
			ss = aes.EecryptToString("段聪wrwe2432v!!1343", key1);			
			System.out.println("明文:段聪wrwe2432v!!1343");
		} catch (InvalidKeyException e)
		{
			e.printStackTrace();
		}		
		aes.Decrypt(dt, key1);
		aes.Decrypt(ss, key1);


主要参考文献:


评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值