非JDK、Java版3DES算法实现源码

不依赖JDK的密码库,纯Java代码实现3DES加密/解密算法,可运行源码如下:

package TDES;

import java.util.Arrays;

public class DES {

	private static final int S_LENGTH = 8;

	// 初始置换表IP,数组长度64
	final byte[] IP_Table = { 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13,
			5, 63, 55, 47, 39, 31, 23, 15, 7, 56, 48, 40, 32, 24, 16, 8, 0, 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44,
			36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6 };

	// 逆初始置换表IP^-1,数组长度64
	final byte[] IP_1_Table = { 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61,
			29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41,
			9, 49, 17, 57, 25, 32, 0, 40, 8, 48, 16, 56, 24 };

	// 扩充置换表E,数组长度48
	final byte[] E_Table = { 31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 9, 10, 11, 12, 11, 12, 13, 14, 15, 16, 15, 16,
			17, 18, 19, 20, 19, 20, 21, 22, 23, 24, 23, 24, 25, 26, 27, 28, 27, 28, 29, 30, 31, 0 };

	// 置换函数P, 数组长度32
	final byte[] P_Table = { 15, 6, 19, 20, 28, 11, 27, 16, 0, 14, 22, 25, 4, 17, 30, 9, 1, 7, 23, 13, 31, 26, 2, 8, 18,
			12, 29, 5, 21, 10, 3, 24 };

	// S盒,三维数组[8][4][16]
	final byte[][][] S =
			// S1
			{ { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
					{ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
					{ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
					{ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } },

					// S2
					{ { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
							{ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
							{ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
							{ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } },

					// S3
					{ { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
							{ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
							{ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
							{ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } },

					// S4
					{ { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
							{ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
							{ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
							{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } },

					// S5
					{ { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
							{ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },
							{ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
							{ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } },

					// S6
					{ { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
							{ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
							{ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
							{ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } },

					// S7
					{ { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
							{ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
							{ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
							{ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } },

					// S8
					{ { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
							{ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
							{ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
							{ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } } };

	// 置换选择1,数组长度56
	final byte[] PC_1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59,
			51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27,
			19, 11, 3 };

	// 置换选择2, 数组长度48
	final byte[] PC_2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51,
			30, 36, 46, 54, 29, 39, 50, 44, 32, 46, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };

	// 对左移次数的规定, 数组长度16
	final byte[] MOVE_TIMES = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };

	private void copy(byte[] sourceArray, byte[] destArray, int length) {
		copy(sourceArray, 0, destArray, 0, sourceArray.length);
	}

	private void copy(byte[] sourceArray, int sourceIndex, byte[] destArray, int destIndex, int length) {
		System.arraycopy(sourceArray, sourceIndex, destArray, destIndex, length);
//		for (int i = 0; i < length; i++) {
//			destArray[destIndex + i] = sourceArray[sourceIndex + i];
//		}
	}

	// 字节转换成二进制
	// 字节转换为二进制
	private byte[] ByteToBit(byte ch) {
		byte[] bit = new byte[S_LENGTH];
		for (int i = 0; i < S_LENGTH; i++) {
			bit[i] = (byte) ((ch >> i) & 1);
		}

		return bit;
	}

	// 二进制转换为字节
	private byte BitToByte(byte[] bit) {
		byte ch = 0;
		for (int i = 0; i < S_LENGTH; i++) {
			ch |= (byte) (bit[i] << i);
		}

		return ch;
	}

	// 将长度为8的字符串转换为二进制位串
	private byte[] Char8ToBit64(byte[] ch) {
		byte[] chs = new byte[64];
		for (int i = 0; i < S_LENGTH; i++) {
			byte[] c = ByteToBit(ch[i]);
			copy(c, 0, chs, S_LENGTH * i, c.length);
		}

		return chs;
	}

	// 将二进制位串转为长度为8的字符串
	private byte[] Bit64ToChar8(byte[] bit) {
		byte[] nc = new byte[S_LENGTH];

		for (int i = 0; i < S_LENGTH; i++) {
			byte[] c = new byte[S_LENGTH];
			copy(bit, i * S_LENGTH, c, 0, S_LENGTH);

			nc[i] = BitToByte(c);
		}

		return nc;
	}

	// 密钥置换1
	byte[] DES_PC1_Transform(byte[] key, byte[] tempbts) {
		byte cnt;
		for (cnt = 0; cnt < 56; cnt++) {
			tempbts[cnt] = key[PC_1[cnt]];
		}
		return tempbts;
	}

	// 密钥置换2
	byte[] DES_PC2_Transform(byte[] key, byte[] tempbts) {
		byte cnt;
		for (cnt = 0; cnt < 48; cnt++) {
			tempbts[cnt] = key[PC_2[cnt]];
		}
		return tempbts;
	}

	// 循环左移
	byte DES_ROL(byte[] data, byte time) {
		byte[] temp = new byte[56];
		// 保存将要循环移动到右边的位
		copy(data, temp, time);
		copy(data, 28, temp, time, time);

		// 前28位移动
		copy(data, time, data, 0, 28 - time);
		copy(temp, 0, data, 28 - time, time);

		// 后28位移动
		copy(data, 28 + time, data, 28, 28 - time);
		copy(temp, time, data, 56 - time, time);
		return 0;
	}

	// IP置换
	byte DES_IP_Transform(byte[] data) {
		byte cnt;
		byte[] temp = new byte[64];
		for (cnt = 0; cnt < 64; cnt++) {
			temp[cnt] = data[IP_Table[cnt]];
		}
		copy(temp, data, 64);
		return 0;
	}

	// IP逆置换
	byte DES_IP_1_Transform(byte[] data) {
		byte cnt;
		byte[] temp = new byte[64];
		for (cnt = 0; cnt < 64; cnt++) {
			temp[cnt] = data[IP_1_Table[cnt]];
		}
		copy(temp, data, 64);
		return 0;
	}

	// 扩展置换
	byte DES_E_Transform(byte[] data) {
		byte cnt;
		byte[] temp = new byte[48];
		for (cnt = 0; cnt < 48; cnt++) {
			temp[cnt] = data[E_Table[cnt]];
		}
		copy(temp, data, 48);
		return 0;
	}

	// P置换
	byte DES_P_Transform(byte[] data) {
		byte cnt;
		byte[] temp = new byte[32];
		for (cnt = 0; cnt < 32; cnt++) {
			temp[cnt] = data[P_Table[cnt]];
		}
		copy(temp, data, 32);
		return 0;
	}

	// 异或
	byte DES_XOR(byte[] R, byte[] L, int count) {
		byte cnt;
		for (cnt = 0; cnt < count; cnt++) {
			R[cnt] ^= L[cnt];
		}
		return 0;
	}

	// S盒置换
	private void DES_SBOX(byte[] data) {
		int line, row, output;
		int cur1, cur2;
		for (int i = 0; i < S_LENGTH; i++) {
			cur1 = i * 6;
			cur2 = i << 2;

			// 计算在S盒中的行与列
			line = (data[cur1] << 1) + data[cur1 + 5];
			row = (data[cur1 + 1] << 3) + (data[cur1 + 2] << 2) + (data[cur1 + 3] << 1) + data[cur1 + 4];
			output = S[i][line][row];

			// 化为二进制
			data[cur2] = (byte) ((output & 0x08) >> 3);
			data[cur2 + 1] = (byte) ((output & 0x04) >> 2);
			data[cur2 + 2] = (byte) ((output & 0x02) >> 1);
			data[cur2 + 3] = (byte) ((output & 0x01));
		}
	}

	// 交换
	byte DES_Swap(byte[] left, byte[] right) {
		byte[] temp = new byte[32];
		System.arraycopy(left, 0, temp, 0, 32);
		System.arraycopy(right, 0, left, 0, 32);
		System.arraycopy(temp, 0, right, 0, 32);
		return 0;
	}

	// 生成子密钥
	byte[][] DES_MakeSubKeys(byte[] key, byte[][] subKeys) {
		byte[] temp = new byte[56];
		byte cnt;
		DES_PC1_Transform(key, temp);// PC1置换
		for (cnt = 0; cnt < 16; cnt++) // 16轮跌代,产生16个子密钥
		{
			DES_ROL(temp, MOVE_TIMES[cnt]);// 循环左移
			DES_PC2_Transform(temp, subKeys[cnt]);// PC2置换,产生子密钥
		}
		return subKeys;
	}

	// 加密单个分组
	private byte[] DES_EncryptBlock(byte[] plainBlock, byte[][] subKeys) {
		byte[] plainBits = Char8ToBit64(plainBlock);
		byte[] temp = new byte[plainBits.length];
		byte[] copyRight = new byte[48];
		// 初始置换(IP置换)
		DES_IP_Transform(plainBits);

		int tempLen = temp.length;
		// 16轮迭代
		for (int i = 0; i < 16; i++) {
			copy(plainBits, 32, copyRight, 0, 32);
			DES_E_Transform(copyRight);
			DES_XOR(copyRight, subKeys[i], 48);
			DES_SBOX(copyRight);
			DES_P_Transform(copyRight);
			DES_XOR(plainBits, copyRight, 32);
			if (i != 15) {
				// 左右部分交换
				copy(plainBits, 0, temp, 32, 32);
				copy(plainBits, 32, temp, 0, 32);
				copy(temp, plainBits, tempLen);
			}
		}

		// 逆初始置换(IP^1置换)
		DES_IP_1_Transform(plainBits);
		return Bit64ToChar8(plainBits);
	}

	// 解密单个分组
	private byte[] DES_DecryptBlock(byte[] cipherBlock, byte[][] subKeys) {
		byte[] cipherBits = Char8ToBit64(cipherBlock);
		byte[] temp = new byte[cipherBits.length];
		byte[] copyRight = new byte[48];

		DES_IP_Transform(cipherBits);

		int tempLen = temp.length;
		// 16轮迭代
		for (int i = 15; i >= 0; i--) {
			copy(cipherBits, 32, copyRight, 0, 32);
			DES_E_Transform(copyRight);
			DES_XOR(copyRight, subKeys[i], 48);
			DES_SBOX(copyRight);
			DES_P_Transform(copyRight);
			DES_XOR(cipherBits, copyRight, 32);
			if (i != 0) {
				// 左右部分交换
				copy(cipherBits, 0, temp, 32, 32);
				copy(cipherBits, 32, temp, 0, 32);
				copy(temp, cipherBits, tempLen);
			}
		}

		// 逆初始置换(IP^1置换)
		DES_IP_1_Transform(cipherBits);
		return Bit64ToChar8(cipherBits);
	}

	// 加密文件
	byte[] DES_Encrypt(byte[] keyStr, byte[] plainFile) {
		byte[] keyBlock = new byte[8];
		byte[] bKey = new byte[64];
		byte[][] subKeys = new byte[16][48];

		System.arraycopy(keyStr, 0, keyBlock, 0, 8); // 设置密钥
		bKey = Char8ToBit64(keyBlock); // 将密钥转换为二进制流
		subKeys = DES_MakeSubKeys(bKey, subKeys); // 生成子密钥

		return DES_EncryptBlock(plainFile, subKeys);
	}

	// 解密文件
	byte[] DES_Decrypt(byte[] keyStr, byte[] cipherFile) {
//		unsigned char plainBlock[8],cipherBlock[8],
//	    unsigned char bKey[64],keyBlock[8],subKeys[16][48];
		byte[] keyBlock = new byte[8];
		byte[] bKey = new byte[64];
		byte[][] subKeys = new byte[16][48];

		System.arraycopy(keyStr, 0, keyBlock, 0, 8); // 设置密钥
		bKey = Char8ToBit64(keyBlock); // 将密钥转换为二进制流
		subKeys = DES_MakeSubKeys(bKey, subKeys); // 生成子密钥

		return DES_DecryptBlock(cipherFile, subKeys);
	}

	/***********************************************************************************************
	 * 作 者:win2kddk 说 明:3重DES是使用16字节密钥将8字节明文数据块进行3次DES加密和解密。
	 ***********************************************************************************************/
	byte[] DES_key = new byte[16];

	byte[] DEC3_Encrypt(byte[] in_buf, byte[] miwen) {
		byte[] buf1 = new byte[8];
		byte[] buf2 = new byte[8];

		byte[] tmpKey = new byte[8];
		for (int i = 0; i < 8; i++) {
			tmpKey[i] = DES_key[i + 8];
		}

		buf1 = DES_Encrypt(DES_key, in_buf);

		buf2 = DES_Decrypt(tmpKey, buf1);
		miwen = DES_Encrypt(DES_key, buf2);

		return miwen;
	}

	byte[] DEC3_Decrypt(byte[] miwen, byte[] out_buf) {
		byte[] buf1 = new byte[8];
		byte[] buf2 = new byte[8];

		byte[] tmpKey = new byte[8];
		for (int i = 0; i < 8; i++) {
			tmpKey[i] = DES_key[i + 8];
		}

		buf1 = DES_Decrypt(DES_key, miwen);
		buf2 = DES_Encrypt(tmpKey, buf1);
		out_buf = DES_Decrypt(DES_key, buf2);

		return out_buf;
	}

	public static String byteArrayToHex(byte[] byteArray) {
		StringBuilder hexString = new StringBuilder();
		for (byte b : byteArray) {
			hexString.append(String.format("%02x", b));
		}
		return hexString.toString().toUpperCase();
	}

	public void DES3_Test() {
		byte[] in_buf = { 'R', 'E', 'I', 'N', 'I', 'T', 0x00, 0x00 };
		byte[] miwen = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
		byte[] out_buf = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

		copy("1036567890XNCDEK".getBytes(), DES_key, 16);// 3DES的密钥是128位的,这里只是设置密钥的DEMO。

		miwen = DEC3_Encrypt(in_buf, miwen); // 3DES加密
		System.out.println("密文:" + byteArrayToHex(miwen));
		out_buf = DEC3_Decrypt(miwen, out_buf); // 3DES解密
		System.out.println("明文:" + new String(out_buf));
	}

	public static void main(String[] args) {
		DES des = new DES();
		des.DES3_Test();
	}

}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值