MD5的概念
MD5算法是单向散列算法的一种。单向散列算法也称为HASH算法,是一种将任意长度的信息压缩至某一固定长度(称之为消息摘要)的函数(该压缩过程不可逆)。在MD5算法中,这个摘要是指将任意数据映射成一个128位长的摘要信息。并且其是不可逆的,即从摘要信息无法反向推演中原文。MD5算法最终生成的是一个128位长的数据,从原理上说,有2^128种可能,这是一个非常巨大的数据,约等于3.4乘10的38次方,虽然这个是个天文数字,但是世界上可以进行加密的数据原则上说是无限的,因此是可能存在不同的内容经过MD5加密后得到同样的摘要信息,但这个碰中的概率非常小。可用于数字签名、信息完整性检查等用途;
注意:md5值不是唯一的,也就是一个原始数据,只对应一个md5值,但是一个md5值,可能对应多个原始数据。且md5值是可以被破解的,例撞库破解
MD5的特点
- 无论输入的消息有多长,加密后的长度总是固定的。
- 一般地,只要输入的消息不同,对其进行加密后产生的内容也必不相同;但相同的输入必会产生相同的输出。
- 只能进行正向的信息加密,而无法从加密内容中恢复出任何的原消息,甚至根本就找不到任何与原信息相关的信息(不可逆性)。
MD5的作用
- 一致性检验,如大文件上传时,需要对文件一致性校验;
- 数字签名,还是最上面那个例子。只是把md5看出了一个指纹,按了个手印说明独一无二了。
- 安全访问认证
如:在用户注册时,会将密码进行md5加密,存到数据库中。这样可以防止那些可以看到数据库数据的人,恶意操作了。
java实现md5加密
1、加密字符串普通不加盐
/**
* 加密字符串普通不加盐
* @param text
*/
public static String msgMD5(String text) {
try {
//1、生成一个MD5加密计算摘要
MessageDigest instance = MessageDigest.getInstance("MD5");
//2 、将消息变成byte数组
byte[] bytes = text.getBytes();
//3 、计算MD5加密后的16字节(128位)摘要
byte[] buff = instance.digest(bytes);
//4 把字节数组转换成16进制字符串
String key = bytesToHex(buff);
return key;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
/**
* 将指定byte数组转换成16进制字符串
* @param bytes
* @return
*/
public static String bytesToHex(byte[] bytes) {
StringBuffer md5str = new StringBuffer();
//把数组每一字节换成16进制连成md5字符串
int digital;
for (int i = 0; i < bytes.length; i++) {
digital = bytes[i];
if(digital < 0) {
digital += 256;
}
if(digital < 16){
md5str.append("0");
}
md5str.append(Integer.toHexString(digital));
}
return md5str.toString().toUpperCase();
}
/**
* 将16进制字符串转换成字节数组
* @param hex
* @return
*/
public static byte[] String16ToBytes(String str) {
if (str == null) {
return null;
}
if (str.length() == 0) {
return new byte[0];
}
byte[] byteArray = new byte[str.length() / 2];
for (int i = 0; i < byteArray.length; i++){
String subStr = str.substring(2 * i, 2 * i + 2);
byteArray[i] = ((byte)Integer.parseInt(subStr, 16));
}
return byteArray;
}
2、 加密字符串普通加盐
/**
* 加密字符串普通加盐
* @param password 待加密数据
* @param salt 盐
* @return
*/
public static String textEncryptMD5(String password,String salt) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
md5.update(salt.getBytes());
byte[] bs = md5.digest(password.getBytes());
StringBuffer hexValue = new StringBuffer();
//循环将字节数组转换成16进制字符串
for (int i = 0; i < bs.length; i++) {
int val = ((int) bs[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
3、加密文件
/**
* 加密文件,不加密
* 1.获取文件的读取流
* 2.不停的读取流中的"内容"放入字符串,放一部分就"更新"一部分.直到全部完毕
* 3.然后调用md5.digest();就会得到有内容的字节数组了.
* @param file
* @return
* @throws Exception
*/
public static String fileEncryptMD5(File file) throws Exception {
String MD5 = "";
MessageDigest md5 = MessageDigest.getInstance("MD5");
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte[1024 * 5];
int len = -1;
while ((len=fis.read(bytes))!=-1) {
md5.update(bytes, 0, len);
}
fis.close();
byte[] digest = md5.digest();
for (int i = 0; i <digest.length; i++) {
int n = digest[i] & 0x000000ff;
String s = Integer.toHexString(n);
MD5 += s;
}
return MD5;
}