简介:四种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的原因,请参考这个写的很不错,我就不写了