参考文献
https://blog.csdn.net/u012598738/article/details/53158443
https://blog.csdn.net/jimi_yuan/article/details/50589069
话不多说直接贴代码
package com.people.test;
import sun.misc.BASE64Decoder;
/**
*密钥分算算法简称Diversify,是指将一个双长度(一个长度密钥为8个字节)的主密钥(MK),对数据进行分散处理,推导出一个双长度的DES加密密钥(DK)。该算法广泛应用于现在的金融IC卡和其他对于安全要求高的行业。其DK推导过程如下:
* 推导DK左半部分的方法是:
* 1、将分散数据的最右8个字节作为输入数据;
* 2、将MK作为加密密钥;
* 3、用MK对输入数据进行3DES运算,得到DK左半部分。
*推导DK右半部分的方法是:
* 1、将分散数据的最右8个字节求反,作为输入数据;
* 2、将MK作为加密密钥;
* 3、用MK对输入数据进行3DES运算,得到DK右半部分
* 最后将DK的左右部分各8个字节合并成双长度的DK密钥,即为分散所求得的待使用的3DES密钥
*
* @author zhaozhiqiang
*
*/
public class DiversifyTest {
public static void main(String atg[]){
String ss= getTransKey("C4D689158AD9FB9D23105B91CE046D0E",
"CE046D0EC4D68915");
System.out.print(ss);
}
/**
* 密钥分散算法
* @param workKey 这里的workKey参数即前面提到的MK,
* @param random random即前面提到的分散数据,都是16进制的数据
* @return
*/
public static String getTransKey(String workKey, String random) {
if (null == workKey || 32 != workKey.length() || null == random || 16 != random.length()) {
return "位数操作有误导";
}
try {
// 计算过程密钥左8字节
byte[] byteKey=new BASE64Decoder().decodeBuffer(workKey);
byte[] byteRandomRight = new byte[8];
byte[] byteRandomLeft = HexCodeUtils.decode(random);
for (int i = 0; i < byteRandomRight.length; i++) {
byteRandomRight[i] = (byte) ~byteRandomLeft[i];
}
//加密
byte[] wkLeft = DESUtils.des3EncodeECB(byteKey, byteRandomLeft);
byte[] wkRight = DESUtils.des3EncodeECB(byteKey,byteRandomRight);
byte[] result = new byte[16];
//加密
for (int i = 0; i < wkLeft.length; i++) {
result[i] = wkLeft[i];
}
for (int i = 8; i < result.length; i++) {
result[i] = wkRight[i - 8];
}
return HexCodeUtils.toHexString(result,0,result.length);
} catch (Exception e) {
return ""+e;
}
}
}
package com.people.test;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* 3des加解密
* @author zhaozhiqiang
*
*/
public class DESUtils {
public static void main(String[] args) throws Exception {
byte[] key=new BASE64Decoder().decodeBuffer("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4");
byte[] keyiv = { 1, 2, 3, 4, 5, 6, 7, 8 };
byte[] data="中国ABCabc123".getBytes("UTF-8");
System.out.println("ECB加密解密");
byte[] str3 = des3EncodeECB(key,data );
byte[] str4 = des3DecodeECB(key,str3);
System.out.println(new BASE64Encoder().encode(str3));
System.out.println(new String(str4, "UTF-8"));
System.out.println("-----------------------------");
System.out.println("CBC加密解密");
byte[] str5 = des3EncodeCBC(key, keyiv, data);
byte[] str6 = des3DecodeCBC(key, keyiv, str5);
System.out.println(new BASE64Encoder().encode(str5));
System.out.println(new String(str6, "UTF-8"));
}
/**
* ECB加密,不要IV
* @param key 密钥
* @param data 明文
* @return Base64编码的密文
* @throws Exception
*/
public static byte[] des3EncodeECB(byte[] key, byte[] data)
throws Exception {
Key deskey = null;
DESedeKeySpec spec = new DESedeKeySpec(key);
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
deskey = keyfactory.generateSecret(spec);
Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, deskey);
byte[] bOut = cipher.doFinal(data);
return bOut;
}
/**
* ECB解密,不要IV
* @param key 密钥
* @param data Base64编码的密文
* @return 明文
* @throws Exception
*/
public static byte[] des3DecodeECB(byte[] key, byte[] data)
throws Exception {
Key deskey = null;
DESedeKeySpec spec = new DESedeKeySpec(key);
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
deskey = keyfactory.generateSecret(spec);
Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, deskey);
byte[] bOut = cipher.doFinal(data);
return bOut;
}
/**
* CBC加密
* @param key 密钥
* @param keyiv IV
* @param data 明文
* @return Base64编码的密文
* @throws Exception
*/
public static byte[] des3EncodeCBC(byte[] key, byte[] keyiv, byte[] data)
throws Exception {
Key deskey = null;
DESedeKeySpec spec = new DESedeKeySpec(key);
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
deskey = keyfactory.generateSecret(spec);
Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
IvParameterSpec ips = new IvParameterSpec(keyiv);
cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
byte[] bOut = cipher.doFinal(data);
return bOut;
}
/**
* CBC解密
* @param key 密钥
* @param keyiv IV
* @param data Base64编码的密文
* @return 明文
* @throws Exception
*/
public static byte[] des3DecodeCBC(byte[] key, byte[] keyiv, byte[] data)
throws Exception {
Key deskey = null;
DESedeKeySpec spec = new DESedeKeySpec(key);
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
deskey = keyfactory.generateSecret(spec);
Cipher cipher = Cipher.getInstance("desede" + "/CBC/PKCS5Padding");
IvParameterSpec ips = new IvParameterSpec(keyiv);
cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
byte[] bOut = cipher.doFinal(data);
return bOut;
}
}
package com.people.test;
/**
* 字节数组互转Hex编码工具类
* @author zhaozhiqiang
*
*/
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.Arrays;
public class HexCodeUtils {
public static void main(String[] args) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
String str = "测试";
byte[] digest = md.digest(str.getBytes());
System.out.println(HexCodeUtils.toHexString(digest));
//db06c78d1e24cf708a14ce81c9b617ec
byte[] bytes = HexCodeUtils.decode("db06c78d1e24cf708a14ce81c9b617ec");
System.out.println(Arrays.equals(digest, bytes));
}
private static final HexEncoder encoder = new HexEncoder();
public static String toHexString(byte[] data) throws IOException {
return toHexString(data, 0, data.length);
}
public static String toHexString(byte[] data, int off, int length) throws IOException {
byte[] encoded = encode(data, off, length);
return new String(encoded);
}
public static byte[] encode(byte[] data) throws IOException {
return encode(data, 0, data.length);
}
public static byte[] encode(byte[] data, int off, int length) throws IOException {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
encoder.encode(data, off, length, bOut);
return bOut.toByteArray();
}
public static int encode(byte[] data, OutputStream out) throws IOException {
return encoder.encode(data, 0, data.length, out);
}
public static int encode(byte[] data, int off, int length, OutputStream out) throws IOException {
return encoder.encode(data, off, length, out);
}
public static byte[] decode(byte[] data) throws IOException {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
encoder.decode(data, 0, data.length, bOut);
return bOut.toByteArray();
}
public static byte[] decode(String data) throws IOException {
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
encoder.decode(data, bOut);
return bOut.toByteArray();
}
public static int decode(String data, OutputStream out) throws IOException {
return encoder.decode(data, out);
}
}
class HexEncoder {
private final byte[] encodingTable = {
(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f'
};
private final byte[] decodingTable = new byte[128];
private void initialiseDecodingTable() {
for ( int i = 0; i < decodingTable.length; i++ ) {
decodingTable[i] = (byte) 0xff;
}
for ( int i = 0; i < encodingTable.length; i++ ) {
decodingTable[encodingTable[i]] = (byte) i;
}
decodingTable['A'] = decodingTable['a'];
decodingTable['B'] = decodingTable['b'];
decodingTable['C'] = decodingTable['c'];
decodingTable['D'] = decodingTable['d'];
decodingTable['E'] = decodingTable['e'];
decodingTable['F'] = decodingTable['f'];
}
public HexEncoder() {
initialiseDecodingTable();
}
private static boolean ignore(char c) {
return c == '\n' || c == '\r' || c == '\t' || c == ' ';
}
public int encode(byte[] data, int off, int length, OutputStream out) throws IOException {
for ( int i = off; i < (off + length); i++ ) {
int v = data[i] & 0xff;
out.write(encodingTable[(v >>> 4)]);
out.write(encodingTable[v & 0xf]);
}
return length * 2;
}
public int decode(byte[] data, int off, int length, OutputStream out) throws IOException {
byte b1, b2;
int outLen = 0;
int end = off + length;
while ( end > off ) {
if ( !ignore((char) data[end - 1]) ) break;
end--;
}
int i = off;
while ( i < end ) {
while ( i < end && ignore((char) data[i]) ) i++;
b1 = decodingTable[data[i++]];
while ( i < end && ignore((char) data[i]) ) i++;
b2 = decodingTable[data[i++]];
if ( (b1 | b2) < 0 ) throw new IOException("invalid characters encountered in Hex data");
out.write((b1 << 4) | b2);
outLen++;
}
return outLen;
}
public int decode(String data, OutputStream out) throws IOException {
byte b1, b2;
int length = 0;
int end = data.length();
while ( end > 0 ) {
if ( !ignore(data.charAt(end - 1)) ) break;
end--;
}
int i = 0;
while ( i < end ) {
while ( i < end && ignore(data.charAt(i)) ) i++;
b1 = decodingTable[data.charAt(i++)];
while ( i < end && ignore(data.charAt(i)) ) i++;
b2 = decodingTable[data.charAt(i++)];
if ( (b1 | b2) < 0 ) throw new IOException("invalid characters encountered in Hex string");
out.write((b1 << 4) | b2);
length++;
}
return length;
}
}