1. 程式人生 > >關於MD5加密中byte陣列轉換成16進位制字串的研究

關於MD5加密中byte陣列轉換成16進位制字串的研究

簡介:四種md5加密,主要區別在於將md5加密後的byte陣列轉換為16進位制字串的方式。

1.第一種,使用bigInteger進行轉換

    public static String md5Encrypt(String src){
        try {
            //獲取md5演算法
            MessageDigest md5Digest = MessageDigest.getInstance("md5");
            //將要加密的字串轉為byte陣列進行加密
            byte[] digest = md5Digest.digest(src.getBytes("utf-8"
)); //將加密後的byte陣列轉換成十六進位制字串 /** * public BigInteger(int signum,byte[] magnitude)將 BigInteger 的符號-數量表示形式轉換為 BigInteger。 * 該符號表示為一個正負號整數值:-1 表示負,0 表示零,1 表示正。 * 該大小是一個 big-endian 位元組順序的 byte 陣列:最高有效位元組在第零個元素中。 * 允許零長度數量陣列,這會導致 BigInteger 的值為 0,無論其正負號是 -1、0 還是 1。 * 引數: * signum - 該數的正負號(-1 表示負,0 表示零,1 表示正)。 * magnitude - 該數的大小的 big-endian 二進位制表示形式。 * 丟擲: * NumberFormatException - signum 不是三個合法值之一(-1、0 和 1),或者 signum 是 0 並且 magnitude 包含一個或多個非零位元組。 * * BigInteger.toString(to) to要轉換成的進位制 * * public String toString(int radix)返回此 BigInteger 的給定基數的字串表示形式。 * 如果該基數超出從 Character.MIN_RADIX 到 Character.MAX_RADIX(包括)這一範圍,則其預設值為 10(Integer.toString 就是這種情況)。 * 使用由 Character.forDigit 提供的從數字到字元的對映,並在需要時在前面加一個負號。(此表示形式與 (String, int) 構造方法相容。) * 引數: * radix - 字串表示形式的基數。 * 返回: * 此 BigInteger 給定基數的字串表示形式。 */
String md5code = new BigInteger(1, digest).toString(16); //如果加密後的md5密文不足32位,前面補0 while (true){ if (md5code.length()<32){ md5code = "0" + md5code; }else { break; } } return
md5code; } catch (Exception e) { //找不到md5演算法,或者加密過程出現異常 e.printStackTrace(); } //出現異常,返回空 return null; }

2.使用Integer.toHexString()進行轉換

    public static String md5Encrypt2(String src){
        try {
            //獲取md5演算法
            MessageDigest md5Digest = MessageDigest.getInstance("md5");
            //將要加密的字串轉為byte陣列進行加密
            byte[] digest = md5Digest.digest(src.getBytes("utf-8"));
            //將加密後的byte陣列轉換成十六進位制字串
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < digest.length; ++i) {
                /*String s = Integer.toHexString(digest[i] & 0xFF);
                //保證全部為兩位,最後結果為32位
                if (s.length() == 1){
                    sb.append("0");
                }*/
                /**
                 * 為了顯示一個byte型的單位元組十六進位制(兩位十六進位制表示)的編碼,請使用:
                 * Integer.toHexString((byteVar & 0x000000FF) | 0xFFFFFF00).substring(6)
                 * byteVar & 0x000000FF的作用是,如果byteVar 是負數,則會清除前面24個零,正的byte整型不受影響。
                 * (...) | 0xFFFFFF00的作用是,如果byteVar 是正數,則置前24位為一,這樣toHexString輸出一個小於等於15的byte整型的十六進位制時,
                 * 倒數第二位為零且不會被丟棄,這樣可以通過substring方法進行擷取最後兩位即可。
                 */
                String s = Integer.toHexString((digest[i] & 0x000000FF) | 0xFFFFFF00).substring(6);
                sb.append(s);
            }
            return sb.toString();
        } catch (Exception e) {
            //找不到md5演算法,或者加密過程出現異常
            e.printStackTrace();
        }
        //出現異常,返回空
        return null;
    }

3.第三種,手動實現進位制轉換

    //16進位制數字陣列
    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
            "8", "9", "a", "b", "c", "d", "e", "f"};

    //將byte陣列轉換成16進位制字串
    public static String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (byte aB : b) {
            resultSb.append(byteToHexString(aB));
        }
        return resultSb.toString();
    }

    //將byte轉為16進位制字串
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n = 256 + n;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    public static String md5Encrypt3(String src){
        String resultString = null;
        try {
            resultString = src;
            //獲取md5演算法
            MessageDigest md = MessageDigest.getInstance("MD5");
            //對字串進行加密,並轉換成16進位制字串
            resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultString;
    }

    //可以選擇指定編碼
    public static String md5Encrypt4(String src, String charsetname){
        String resultString = null;
        try {
            resultString = src;
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname)){
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            } else {
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultString;
    }

4.使用apache工具類進行轉換

    public static String md5Encrypt5(String src){
        String resultString = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(src.getBytes("utf-8"));
            resultString = Hex.encodeHexString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultString;
    }

Apache轉換原始碼:

    protected static char[] encodeHex(final byte[] data, final char[] toDigits) {
        final int l = data.length;
        final char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
            out[j++] = toDigits[0x0F & data[i]];
        }
        return out;
    }

5.測試程式碼

    public static void main(String[] args) {
        String md5Encrypt = md5Encrypt("shaoyuanhu");
        System.out.println(md5Encrypt);
        System.out.println(md5Encrypt.length());
        String md5Encrypt2 = md5Encrypt2("shaoyuanhu");
        System.out.println(md5Encrypt2);
        System.out.println(md5Encrypt2.length());
        String md5Encrypt3 = md5Encrypt3("shaoyuanhu");
        System.out.println(md5Encrypt3);
        System.out.println(md5Encrypt3.length());
        String md5Encrypt4 = md5Encrypt4("shaoyuanhu",null);
        System.out.println(md5Encrypt4);
        System.out.println(md5Encrypt4.length());
        String md5Encrypt5 = md5Encrypt5("shaoyuanhu");
        System.out.println(md5Encrypt5);
        System.out.println(md5Encrypt5.length());
    }

6.關於byte&0xFF的原因,請參考這個寫的很不錯,我就不寫了