JAVA中的MD5加密,常見問題處理

平常使用MD5加密時,自己封裝處理時,常見有2個問題:

1、轉換爲字符串時,高位的0被捨去;

2、出現負數時會有多個連續的F;

這是因爲MessageDigest返回的結果是無符號數的byte數組,所以一個byte表示2位的十六進制數時,高位可能爲0,而且在JAVA中byte默認是按有符號數的來讀取的,轉換時會出現負數。

public class MD5Utils {
    
    private static final char[] chs =
            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    
    public static String getMD5(String str) {
        MessageDigest messageDigest;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalArgumentException();
        }
        byte[] bys = messageDigest.digest(str.getBytes());
        StringBuilder sb = new StringBuilder(32);
        int index;
        for (byte b : bys) {
            index = b & 0xff;//將負數byte按無符號數讀取
            sb.append(chs[index >> 4]);//16進制數的高位
            sb.append(chs[index % 16]);//16進制數的低位
        }
        return sb.toString();//返回的結果爲32位的16進制數字符串
    }
}

其中,因爲MessageDigest返回的結果是用無符號數來表示的,而在JAVA中默認是採用最高位來表示正負的,所以使用了位運算的方式來截取該無符號數:

		   index = b & 0xff;


等價於:

			   index = b;
			   if(index < 0 ){
				   index += 256;
			   }

 

一個byte可以表示2位的16進制數,採用Integer.toHexString(index)轉換時,若小於16會只有1位16進制數。繼續使用位運算+查表法來獲取16進制數:

		       sb.append(chs[ index >> 4]);
		       sb.append(chs[ index % 16]);
等價於:
               if(index < 16){
                   sb.append('0');
               }
               sb.append(Integer.toHexString(index));
因爲沒有使用Integer的toHexString(index)和toString(int i, int radix)方法,而是自己重新實現了,所以效率有所提高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章