使用JAVA進行MD5加密後所遇到的一些問題
https://www.cnblogs.com/renchunxiao/p/3411370.html 原創。本篇為轉載方便自我使用。
前言:這幾天在研究apache shiro如何使用,這好用到了給密碼加密的地方,就碰巧研究了下java的MD5加密是如何實現的,下面記錄下我遇到的一些小問題。
使用java進行MD5加密非常的簡單,程式碼如下:
public static void main(String[] args) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); String password= "wodemima"; byte[] bytes = md5.digest(password.getBytes()); }
但是,當我將bytes直接轉換成字串並且存入資料庫的時候我發現了問題,怎麼顯示的是個亂碼呢,顯示的是如下亂碼:
�'D���:�@� ��&
我頓時感覺這真是加密了,肯定妥妥的破解不了,但是一般加密後顯示的是32位16進位制字串,為什麼我這顯示亂碼了呢。原來是還有一個步驟,就是需要將byte陣列轉換成16進行,程式碼如下:
public static void main(String[] args) throws Exception { MessageDigest md5= MessageDigest.getInstance("MD5"); String password = "wodemima"; byte[] bytes = md5.digest(password.getBytes()); String result = ""; for(byte b : bytes) { result = result + Integer.toHexString(b); } System.out.println(result); }
//輸出顯示:fffffffb2744ffffffd1ffffffe419ffffff813affffffde40ffffffefaffffff97ffffffc5261f
這下子算是像模像樣了,但是貌似不是32位,並且有好多fff,原來是返回的byte陣列當中有負數,但是有負數為什麼會造成這樣的結果呢,於是乎我就複習了下java當中的基本型別。
基本型別表如下:
資料型別 大小 範圍 預設值 byte(位元組) 8 -128 - 127 0 shot(短整型) 16 -32768 - 32767 0 int(整型) 32 -2147483648 - 2147483647 0 long(長整型) 64 -9233372036854477808-9233372036854477807 0 float(浮點型) 32 1.4E-45 - 3.40292347E+38 0.0f double(雙精度) 64 4.9E-324 - 1.79769313486231570E+308 0.0d char(字元型) 16 ‘ \u0000 - u\ffff ’ ‘\u0000 ’ boolean(布林型) 1 true/false false
我原來上大學的時候一直在困惑為什麼佔8位最大值不是128,後來我發現原來還有個0呢。。不知道算不算是頓悟。。。。。
於Integer.toHexString(b);方法傳入的值是int型別的,所以當我傳入byte的時候就會自動轉換成int型別,又由於byte型別只佔8位並且int型別佔32位,所以會進行補位,如果byte是整數的話沒什麼影響,因為前面補的是0。
但是如果是負數的話就會出現問題了,例如byte b = -112; byte的2進製表示為:1001 0000,java中是以補碼的形式進行表示的。(補碼我就不介紹了,可以百度查閱。)這樣前面補滿22位個1的時候就會出現很多f。
於是我把程式碼改成下面這個樣子:
public static void main(String[] args) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); String password = "wodemima"; byte[] bytes = md5.digest(password.getBytes()); String result = ""; for(byte b : bytes) { result = result + Integer.toHexString(b & 0xff);
//b & 0xff 是為了取低8位
}
System.out.println(result);
}
//輸出顯示:fb2744d1e419813ade40efa97c5261f
這次更像那麼回事了,但是我查了一下31位。為什麼會少一位,原來byte陣列中有的值可能小於16,所以轉換成16進位制的時候用1位就可以表示了。這個時候我們應該在前面加上個0。
程式碼如下:
public static void main(String[] args) throws Exception { MessageDigest md5 = MessageDigest.getInstance("MD5"); String password = "wodemima"; byte[] bytes = md5.digest(password.getBytes()); String result = ""; for(byte b : bytes) { String temp = Integer.toHexString(b & 0xff); if(temp.length() == 1) { temp = "0" + temp; } result = result + temp; } System.out.println(result); }
//輸出顯示:fb2744d1e419813ade40ef0a97c5261f
好了,這次正確了。這就是我記錄的一些問題,有些細節不注意還真不知道怎麼回事