參考文獻
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;
}
}