理解 MD5
MD5 的应用非常广泛 h5 棋牌源码租用 (h5.hxforum.com) 联系 170618633533 企鹅 2952777280( http://yhgj8004.com) 源码出售 房卡出售 后台出租联系方式只有企鹅.例如我们在 unix 中下载某种软件时,常常会看到一个扩展名为. md5 的文件,内容大概是:
MD5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461
这就是 tanajiya.tar.gz 文件的数字签名.因此当我们得到这个文件后,使用工具计算该文件对应的 md5 值,然后和文件中记录的. md5 中记录的值进行对比,如果不一致,就可以得知文件内容发生了变化.
MD5 算法将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的 MD5 信息摘要.这就相当于这个文件的指纹,如果有任何人修改了文件内容,或下载文件由于网络问题不完整,则生成的 md5 值也会发生变化.
MD5 算法本质是一个哈希算法,因此 MD5 值就是一个哈希值.由这个例子可以得知 MD5 的一些特点:
1,对于同样的文件,计算出的 MD5 值永远是一样的.MD5 算法中没有任何随机数或不确定因素.
2,MD5 算法是公开的.因而我们可以找到很多个 MD5 生成器,但背后的算法是一样的.
3,我们可以认为世界上的文件是无限的,而得到的 MD5 值永远是一个 128 位二进制数.因此是一个无穷序列到一个有限序列的映射.进而可以得知,MD5 算法是不可逆的,也就是说,我们不能用一个 MD5 值来推算出源文件的内容.
4,从无穷序列到有限序列的映射这点又可以推断出,MD5 算法可能产生冲突 (这也是所有哈希函数都会遇到的问题).即两个不同的文件,可能会产生一样的 MD5 值.我们知道 2^128 次方是个巨大无比的数字,因此之前认为 MD5 的冲突在理论上存在,现实生活中遇到的可能性很低,因此是个可靠的算法.然而近年研究出的碰撞算法使得计算机在很短的时间内就可以得出一个可能的冲突值,这就是 MD5 算法的缺陷.我们在后面会提到这种缺陷的危害.
MD5 的其它应用
数字证书
和前面的例子一样,在发行软件的时候,附带一个 MD5 证书.如果再有一个第三方的认证机构,用 MD5 还可以防止文件作者的 "抵赖",这就是所谓的数字签名应用.
安全认证
MD5 还广泛用于操作系统的登陆认证上,如 Unix,各类 BSD 系统登录密码,数字签名等诸多方面.如在 UNⅨ 系统中用户的密码是以 MD5(或其它类似的算法)经 Hash 运算后存储在文件系统中.当用户登录的时候,系统把用户输入的密码进行 MD5 Hash 运算,然后再去和保存在文件系统中的 MD5 值进行比较,进而确定输入的密码是否正确.通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性.这可以避免用户的密码被具有系统管理员权限的用户知道.如果用户丢失了密码,只能让管理员重置密码.
MD5 的缺陷
前面提到 MD5 的破解算法,也称为碰撞算法.本质就是对于一个给定的 MD5,在很短的时间内就能找到可能的源文件内容.前面提到 MD5 算法是不可逆的,也就是说破解算法不能保证得到的一定是源文件内容,但是能保证该文件内容计算出的 MD5 值一定和源文件产生的 MD5 相同.我们来看看这有什么危害:比如用户的登录密码为 666666,后台数据库存储的是 MD5 值,假如是 0ca175b9c0f726a831d895e269332461.破解的人拿到这个 MD5 值,使用破解算法计算出和这个 MD5 碰撞的密码,假如是 678865.
这样破解的人就可以使用 678865 去登录,由于 MD5 的输出还是 0ca175b9c0f726a831d895e269332461,因此这个人就可以顺利登录.
对于这个问题,一个很容易的解决方案是,将用户输入的初始密码复制一份,变成 666666666666,然后产生 MD5,存入数据库.这样破解算法得到的可能的密码就不再是 678865 了,他也无法用这个可能密码去登录.
除了碰撞算法破解以外,现在被黑客使用最多的一种破译密码的方法就是一种被称为 "跑字典" 的暴力破解方法 (brute force).有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用 MD5 程序计算出这些字典项的 MD5 值,然后再用目标的 MD5 值在这个字典中检索.我们假设密码的最大长度为 8 位字节(8 Bytes),同时密码只能是字母和数字,共 26+26+10=62 个字符,排列组合出的字典的项数则是 P(62,1)+P(62,2)....+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要 TB 级的磁盘阵列,而且这种方法还有一个前提,就是能获得目标账户的密码 MD5 值的情况下才可以.这种加密技术被广泛的应用于 UNⅨ 系统中,这也是为什么 UNⅨ 系统比一般操作系统更为坚固一个重要原因.
简单 MD5 类
[java] view plain copy
import java.security.MessageDigest;
public class MD5Demo {
public static class MD5_test {
public final static String MD5(String s) {
char hexDigits[] = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' ,
'a' , 'b' , 'c' , 'd' , 'e' , 'f' };
try {
byte [] strTemp = s.getBytes();
MessageDigest mdTemp = MessageDigest.getInstance("MD5" );
mdTemp.update(strTemp);
byte [] md = mdTemp.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 ;
}
}
public static void main(String[] args) {
// MD5_test aa = new MD5_test();
System.out.print(MD5_test.MD5("b"));
}
}
}
加密 ---------- 解密 MD5 类
[java] view plain copy import java.security.MessageDigest;
public class MD5andKL {
// MD5 加码.32 位
public static String MD5(String inStr) {
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
return "";
}
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i];
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
// 可逆的加密算法
public static String KL(String inStr) {
// String s = new String(inStr);
char[] a = inStr.toCharArray();
for (int i = 0; i < a.length; i++) {
a[i] = (char)(a[i] ^ 't');
}
String s = new String(a);
return s;
}
// 加密后解密
public static String JM(String inStr) {
char[] a = inStr.toCharArray();
for (int i = 0; i < a.length; i++) {
a[i] = (char)(a[i] ^ 't');
}
String k = new String(a);
return k;
}
// 测试主函数
public static void main(String args[]) {
String s = new String("a");
System.out.println("原始:" + s);
System.out.println("MD5 后:" + MD5(s));
System.out.println("MD5 后再加密:" + KL(MD5(s)));
System.out.println("解密为 MD5 后的:" + JM(KL(MD5(s))));
}
}
来源: http://www.bubuko.com/infodetail-2473454.html