1. 程式人生 > >Java 10進位制byte陣列與16進位制byte陣列互轉 及 在DES加解密中的使用

Java 10進位制byte陣列與16進位制byte陣列互轉 及 在DES加解密中的使用

一、10進位制byte陣列與16進位制byte陣列互轉

1. 10進位制byte陣列轉成16進位制byte陣列

Java中10進位制byte用二進位制表示佔用8位,16進位制的每個字元需要用4位二進位制位來表示,則將每一個10進位制

位元組的高4位、低4位分別進行處理,對應到16進位制字元(通過與0xf0或0x0f進行&位運算將4位轉成0~15範圍內

的一個數,與這個數對應的有一個16進位制字元),取該字元對應的位元組,最終組成一個16進位制位元組陣列。

2. 10進位制byte陣列轉成16進位制byte陣列

      處理過程與上面的正好相反。16進位制的兩個位元組對應到10進位制位元組的一個位元組,則將相鄰兩個16進位制位元組的

第一個位元組對應到16進位制數字並向左移動4位(作為10進位制位元組的高4位)、第二個位元組對應到16進位制數字,並

將兩者進行|位運算,結果作為一個10進位制位元組,最終組成一個10進位制位元組陣列

程式碼實現如下:
/**
 * 
* ClassName: HexUtil <br/> 
* Function: 16進位制位元組陣列與10進位制位元組陣列轉換工具類 <br/> 
* date: 2017年1月23日 下午10:58:17 <br/> 
* 
* @author JohnFNash 
* @version  
* @since JDK 1.6
 */
public class HexUtil {

	/** 16進制中的字符集 */
	private static final String HEX_CHAR = "0123456789ABCDEF";
	
	/** 16進制中的字符集對應的位元組陣列 */
	private static final byte[] HEX_STRING_BYTE = HEX_CHAR.getBytes();
	
	/**
	 * 10進位制位元組陣列轉換為16進位制位元組陣列
	 * 
	 * byte用二進位制表示佔用8位,16進位制的每個字元需要用4位二進位制位來表示,則可以把每個byte
	 * 轉換成兩個相應的16進位制字元,即把byte的高4位和低4位分別轉換成相應的16進位制字元,再取對應16進位制字元的位元組
	 * 
	 * @param b 10進位制位元組陣列
	 * @return 16進位制位元組陣列
	 */
	public static byte[] byte2hex(byte[] b) {
		int length = b.length;
		byte[] b2 = new byte[length << 1];
		int pos;
		for(int i=0; i<length; i++) {
			pos = 2*i;
			b2[pos] = HEX_STRING_BYTE[(b[i] & 0xf0) >> 4];
			b2[pos+1] = HEX_STRING_BYTE[b[i] & 0x0f];
		}
		return b2;
	}
	
	/**
	 * 16進位制位元組陣列轉換為10進位制位元組陣列
	 * 
	 * 兩個16進位制位元組對應一個10進位制位元組,則將第一個16進位制位元組對應成16進位制字元表中的位置(0~15)並向左移動4位,
	 * 再與第二個16進位制位元組對應成16進位制字元表中的位置(0~15)進行或運算,則得到對應的10進位制位元組
	 * @param b 10進位制位元組陣列
	 * @return 16進位制位元組陣列
	 */
	public static byte[] hex2byte(byte[] b) {
		if(b.length%2 != 0) {
    		throw new IllegalArgumentException("byte array length is not even!");
    	}
		
		int length = b.length >> 1;
		byte[] b2 = new byte[length];
		int pos;
		for(int i=0; i<length; i++) {
			pos = i << 1;
			b2[i] = (byte) (HEX_CHAR.indexOf( b[pos] ) << 4 | HEX_CHAR.indexOf( b[pos+1] ) );
		}
		return b2;
	}
	
	/**
	 * 將16進位制位元組陣列轉成10進位制字串
	 * @param b 16進位制位元組陣列
	 * @return 10進位制字串
	 */
	public static String hex2Str(byte[] b) {
		return new String(hex2byte(b));
	}
	
	/**
	 * 將10進位制位元組陣列轉成16進位制字串
	 * @param b 10進位制位元組陣列
	 * @return 16進位制字串
	 */
	public static String byte2HexStr(byte[] b) {
		return Integer.toHexString(Integer.parseInt(new String(b)));
	}
	
	public static void main(String[] args) {
		System.out.println(hex2Str(byte2hex("60".getBytes())));
		System.out.println(byte2HexStr("60".getBytes()));
	}
	
}
二、DES加解密

使用Java提供的工具類實現DES加解密

1. DES加密

      先使用java提供的工具類加密得到10進位制位元組陣列,再將10進位制位元組陣列轉成16進位制位元組陣列(使用上面

進位制轉換的工具類),最後將16進位制位元組陣列轉成16進位制字串。

2. DES解密

       先將16進位制字串對應的位元組陣列轉成10進位制位元組陣列,再將10進位制位元組陣列使用java提供的工具類進行

解密,最後將解密得到的位元組陣列轉成10進位制字串。

程式碼實現如下:

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

/**
 * 
* ClassName: EncryptUtil <br/> 
* Function: 加解密工具類 <br/> 
* date: 2017年1月22日 下午9:12:22 <br/> 
* 
* @author JohnFNash 
* @version  
* @since JDK 1.6
 */
public class EncryptUtil {

	/** 加密、解密key. */
    private static final String PASSWORD_CRYPT_KEY = "johnfnash";
    
    /** 加密、解密key對應位元組陣列. */
    private static final byte[] PASSWORD_CRYPT_KEY_BYTE = PASSWORD_CRYPT_KEY.getBytes();
    
    /** 加密演算法,可用 DES,DESede,Blowfish. */
    private final static String ALGORITHM = "DES";
    
    /**
     * 用DES對資料進行加密(先加密得到10進位制位元組陣列,再將10進位制位元組陣列轉成16進位制位元組陣列,最後將16進位制位元組陣列轉成16進位制字串)
     * @param data 待加密資料
     * @return 加密後的資料
     * @throws Exception
     */
    public final static String encrypt(String data) throws Exception {
    	return new String(HexUtil.byte2hex(encrypt(data.getBytes(), PASSWORD_CRYPT_KEY_BYTE)));
    }
    
    /**
     * 用指定的key對資料進行DES加密.
     * @param data 待加密的資料
     * @param key DES加密的key
     * @return 返回DES加密後的資料
     * @throws Exception
     */
    private static byte[] encrypt(byte[] data, byte[] key) throws Exception {
    	return operate(data, key, Cipher.ENCRYPT_MODE);
    }
    
    /**
     * 用DES對資料進行解密(先將16進位制字串對應的位元組陣列轉成10進位制位元組陣列,再將10進位制位元組陣列進行解密,最後將解密得到的位元組陣列轉成10進位制字串)
     * @param data 加密資料
     * @return 解密後的資料
     * @throws Exception
     */
    public final static String decrypt(String data) throws Exception {
    	return new String(decrypt(HexUtil.hex2byte(data.getBytes()), PASSWORD_CRYPT_KEY_BYTE));
    }
    
    /**
     * 用指定的key對資料進行DES解密
     * @param data 帶解密的資料
     * @param key DES解密的key
     * @return 解密後的資料
     * @throws Exception
     */
    private static byte[] decrypt(byte[] data, byte[] key) throws Exception {
    	return operate(data, key, Cipher.DECRYPT_MODE);
    }

    /**
     * 加密/解密操作
     * @param data 待加密/解密資料
     * @param key 加密/解密的key
     * @param opMode 操作模式,Cipher.ENCRYPT_MODE(加密)/Cipher.DECRYPT_MODE(解密)
     * @return 加密/解密的結果
     * @throws Exception
     */
    private static byte[] operate(byte[] data, byte[]key, int opMode) throws Exception {
    	// DES演算法要求有一個可信任的隨機數源
    	SecureRandom sr = new SecureRandom();
    	// 從原始金鑰資料建立DESKeySpec物件
    	DESKeySpec dks =  new DESKeySpec(key);
    	// 建立一個金鑰工廠,然後用它把DESKeySpec轉換成一個SecretKey物件
    	SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
    	SecretKey secretKey = keyFactory.generateSecret(dks);
    	// Cipher物件實際完成加密/解密操作
    	Cipher cipher = Cipher.getInstance(ALGORITHM);
    	// 用金鑰初始化Cipher物件
    	cipher.init(opMode, secretKey, sr);
    	// 獲取資料並加密/解密
    	return cipher.doFinal(data);
    }
    
    public static void main(String[] args) throws Exception {
    	String user = "root";
    	System.out.println("加密後的使用者名稱: " + encrypt(user));
    	System.out.println("解密後的使用者名稱: " + decrypt(encrypt(user)));
	}
    
}

參考文章: