不依赖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();
}
}