MD5加密
来源:互联网 发布:网络人远程控制 编辑:程序博客网 时间:2024/06/05 00:55
Md5加密原理
MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
在MD5算法中,首先需要对信息进行填充,使其字节长度对512求余数的结果等于448。因此,信息的字节长度(Bits Length)将被扩展至N*512+448,即N*64+56个字节(Bytes),N为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后再在这个结果后面附加一个以64位二进制表示的填充前的信息长度。经过这两步的处理,现在的信息字节长度=N*512+448+64=(N+1)*512,即长度恰好是512的整数倍数。这样做的原因是为满足后面处理中对信息长度的要求。MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210。 当设置好这四个链接变量后,就开始进入算法的四轮循环运算,循环的次数是信息中512位信息分组的数目。
将上面四个链接变量复制到另外四个变量中:A到a,B到b,C到c,D到d。 主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量(文本中的一个子分组和一个常数)。
再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。 以一下是每次操作中用到的四个非线性函数(每轮一个)。
F(X,Y,Z)=(X∧Y)∨(( X)∧Z)G(X,Y,Z)=(X∧Z)∨(Y∧( Z))H(X,Y,Z)=X?Y?ZI(X,Y,Z)=Y?(X∨( Z))
其中,?是异或,∧是与,∨是或, 是反符号。
如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。F是一个逐位运算的函数。即,如果X,那么Y,否则Z。函数H是逐位奇偶操作符。所有这些完成之后,将A,B,C,D分别加上a,b,c,d。然后用下一分组数据继续运行算法,最后的输出是A,B,C和D的级联。最后得到的A,B,C,D就是输出结果,A是低位,D为高位,DCBA组成128位输出结果。
2.2 MD5的安全性
从安全的角度讲,MD5的输出为128位,若采用纯强力攻击寻找一个消息具有给定Hash值的计算困难性为2128,用每秒可试验1000000000个消息的计算机需时1.07×1022年。若采用生日攻击法,寻找有相同Hash值的两个消息需要试验264个消息,用每秒可试验1000000000个消息的计算机需时585年。
2.3 Md5加密算法的应用
MD5加密算法由于其具有较好的安全性,加之商业也可以免费使用该算法,因此该加密算法被广泛使用,md5算法主要运用在数字签名、文件完整性验证以及口令加密等方面。
3.改进后的加密方法
3.1目前md5加密方法利用的缺陷
在目前的信息系统中,对md5加密方法的利用主要通过在脚本页面中引用包含md5加密函数代码的文件,以asp脚本为例,在需要调用的页面中加入,md5.asp为md5加密函数代码文件,然后直接调用函数MD5(sMessage)即可,md5加密后的值有16位和32位之分,如果在md5加密函数中使用的是MD5 = LCase(WordToHex(a) & WordToHex(b) & WordToHex(c) & WordToHex(d)),则表示是32位,如果使用的是MD5=LCase(WordToHex(b) & WordToHex(c)),则表示是16位。例如对明文为“123456”的值进行加密,其md5值有两个,如下所示:
A=“123456”password=md5(A)= 49ba59abbe56e057 password=md5(A)= e10adc3949ba59abbe56e057f20f883e
如果将加密的md5值直接保存在数据库,当网站存在注入或者其它漏洞时,入侵者极有可能获取用户的密码值,通过md5在线查询或者暴力破解可以得到密码。
MD5加密工具类
package day18;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5Object {
private static MessageDigest md = null;
private static MessageDigest sha = null;
private static long jishu[] = new long[8];
static {
try {
md = MessageDigest.getInstance("MD5");
sha = MessageDigest.getInstance("SHA-1");
jishu[0] = 1;
for ( int i = 1; i < 8; i++) {
jishu[i] = jishu[i-1]*256;
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public String SHASum(String input) {
if (sha == null || input == null) {
return null;
}
sha.reset();
sha.update(input.getBytes());
byte[] sign = sha.digest();
return bytes2Hex(sign);
}
public static String MD5Sum(String input) {
if ( md == null ) {
return null;
}
if ( input == null) {
return null;
}
md.reset();
md.update(input.getBytes());
byte[] sign = md.digest();
return bytes2Hex(sign);
}
public Long MD5To64Bit(String input) {
if ( md == null ) {
return null;
}
if ( input == null) {
return null;
}
md.reset();
md.update(input.getBytes());
byte[] sign = md.digest();
long fst = transfer64bitsTolong(sign, 0);
long second = transfer64bitsTolong(sign, 8);
return Long.valueOf(fst + second);
}
private long transfer64bitsTolong(byte[] input, int start) {
long result = 0;
if (start + 8 <= input.length) {
int tmp = 0;
for ( int i = 0; i < 7 ; i++ ) {
tmp = Byte.valueOf(input[start + i]).intValue();
if ( tmp < 0) {
tmp = tmp & 0x7f + 0x80;
}
result = result + tmp*jishu[i];
}
int last = Byte.valueOf(input[start + 7]).intValue();
if ( last < 0 ) {
last = last & 0x7f;
result = last * jishu[7] + result;
result = Long.MIN_VALUE + result;
} else {
result = last * jishu[7] + result;
}
}
return result;
}
/**
* 将字节数组转换成16进制的字符串
* @param bts
* @return
*/
private static String bytes2Hex(byte[] bts) {
String des = "";
String tmp = null;
for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1) {
des += "0";
}
des += tmp;
}
return des;
}
public static void main(String[] args) {
MD5Object md5 = new MD5Object();
System.out.println(md5.MD5Sum("zpf1993"));
}
}
- MD5加密
- MD5加密
- md5加密
- MD5加密
- md5加密
- MD5加密
- MD5加密
- md5 加密
- MD5加密
- md5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- MD5加密
- js易错点总结
- hbase数据的存放顺序
- STL中常用数据结构
- g++ windows 编译 (cmd指令)
- C++ Primer(第五版)练习3.32
- MD5加密
- WSGI、webob、routes实例
- Linux命令-tail
- 二叉树的深度优先遍历和广度优先遍历
- html5 canvas学习--canvas保存于恢复状态
- git仓库的建立与git服务器的搭建
- 一维数组与二维数组
- 前端面试宝典(内容很多,也有很多重复)
- 附加没有日志文件的数据库文件