關於MD5加密中byte陣列轉換成16進位制字串的研究
阿新 • • 發佈:2019-01-27
簡介:四種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的原因,請參考這個寫的很不錯,我就不寫了