1. 程式人生 > >使用JAVA進行MD5加密後所遇到的一些問題

使用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

   好了,這次正確了。這就是我記錄的一些問題,有些細節不注意還真不知道怎麼回事