一.MD5的简单理解
MD5的全称是Message-Digest Algorithm 5(信息摘要算法),它面向的是32位的电脑,MD5算法会获得一个随机的长度的信息并产生一个128位的信息摘要,(也就是说可以生成一个固定长度为128bit的二进制串)。它是一个信息摘要算法,而摘要和加密是有区别的。1.1.摘要
摘要是哈希值,我们可以通过散列算法比如MD5算法得到哈希值。它只是用于验证数据完整性和唯一性的哈希值,不管原始数据是什么样的,得到的哈希值都是固定长度并且并不是直接由原始数据加密后的密文,只是根据原始数据生成了一个验证身份的令牌。所以我们无法通过摘要解密得到原始数据。
1.2.加密
加密是加密算法直接由明文加密成为密文,我们可以通过秘钥和解密算法将密文准确的还原成明文。
二.MD5算法的特点
2.1.压缩性
任意长度的数据计算出的MD5值得长度都是固定的。存储和管理比较方便。
2.2.易于计算
数据计算出MD5值很容易,易于使用者的理解和使用 。
2.3.细微性
任意大小的数据,只要经过任何的改变,哪怕只修改某个字节,所得到的MD5值都会有很大的区别,这个特点常被用于文件下载的检验。
2.4.不可逆性
得到一个MD5值,无法反向计算出原数据
2.5.弱相同性
一个数据对应一个MD5值,一个MD5值可能对应多个原始数据。
三.MD5破解讲解
MD5破解的方式,因为MD5算法是不可逆的,所以破解一般是"撞库破解",也就是把大量的常用的语句经过MD5"加密"后放入数据库,再把你输入的语句经过MD5"加密"去和数据库中的MD5值对比,然后返回原语句,这样只能找出一些简单的,常用的语句
四.MD5的加盐
单纯的将数据MD5"加密"后,也有被对比,暴力破解的风险,所以我们需要加盐,通俗来说就是在原数据中加入其他的数据,比如密码(password),随机数(random number),得到password的MD5值然后加上random number然后再次MD5后,得到这个MD5值,这就是个简单的加盐过程,这样的话就算得到最后的这个MD5值得原数据,也得不到password。
五.MD5值的位数
前面说了MD5后值为128bit的二进制串,但二进制都是01,会造成用户的使用,理解不便,所以将128bit的二进制串转化为16进制的串,所以就输出的MD5值为32位。16位的MD5值是从32位的MD5值抽取出来的,32位MD5值去掉前后的八位,得到的值就是16位的MD5值。
六.MD5工具类(java)
public class MD5Util {
private final static char hexDigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
//MD5加密的普通方式
public static String getMD5(String key){
try {
byte[] btInput = key.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
}
//MD5加密的另一种方式
public static String getOtherMD5(String key) {
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
messageDigest.reset();
messageDigest.update(key.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
}
byte[] byteArray = messageDigest.digest();
StringBuffer md5StrBuff = new StringBuffer();
for (int i = 0; i < byteArray.length; i++) {
if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
else
md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
}
return md5StrBuff.toString();
}
// 加密后解密,一次是加密,两次解密
public static String encrypt(String key) {
char[] a = key.toCharArray();
for (int i = 0; i < a.length; i++) {
a[i] = (char) (a[i] ^ 't');
}
String k = new String(a);
return k;
}
}
或者使用commons-codecjar包,我这里使用的是依赖
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>