您的位置:首页 > 编程语言 > Java开发

MD5算法介绍及jdk自带实现方式

2015-07-31 14:08 501 查看
MD5算法,已经被人们熟知,作为一名资深或者入门级的开发者,都号称“MD5啊,知道知道“。前几天程序略有小问题,原因是有的地方加密了,有的地方没加密。有个同事很得意的说,MD5就是个hash算法,很容易被解密的。当时我是无言以对了。因为俺记得MD5是不可逆的,既然不可逆,又哪里来的”解密“呢。于是我们在网上搜索“MD5解密”,哇kao,竟然真的有结果,然则,事实并非那么简单,我们把MD5的一串序列放到“在线MD5解密”中去解密,大部分都没有被破解。其中一个显示说找到了,但是要付费。。。

自此该哥们还是不服,非说MD5是可以破解的。我竟然再次无言以对了。你说世界上有可以不被破解的加密吗??!!国防局那么厉害不照样被各种黑客攻击吗?话说,如果有一种加密算法可以不被破解,世界上还有黑客吗?

任何一种算法都是会被破解的,只不过是时间的问题。那么我们为什么还要加密哩?因为不是每个人都有足够的时间去破解你的密码,但是每个人都有足够的时间去抓取你的明文。这就是加密的意义所在。

好了,下面我来简单说明一下MD5算法的原理:

1、概念及发展历史:

MD5的全称[3]是Message-Digest algorithm 5(信息--摘要算法),MD5是一种不可逆的算法,即对生成的密文求逆,对应着无穷多个逆。在90年代初由MIT Laboratory for Computer Science(IT计算机科学实验室)和RSA Data Security Inc(RSA数据安全公司)的Ronald L.Rivest开发出来,经MD2,MD3和MD4发展而来。

它的作用是让大容量信息在用数字签名软件签署私人密钥前被“压缩”成一种保密的格式(把一个任意长度的字节串变换成一定长的大整数)。不管是MD2,MD4还是MD5,它们都需要获得一个随机长度的信息,并产生一个128位的信息摘要。虽然这些算法的结构或多或少有些相似,但是MD2的设计与MD4和MD5完全不同,是因为MD2是为8位机器做过设计优化的,而MD4和MD5却是面向32位的电脑。Rivest在1989年开发出MD2算法,在这个算法中,首先对信息进行数据补位,使信息的字节长度是16的倍数,然后,以一个16位的检验和追加到信息末尾,并且根据这个新产生的信息计算出散列值。后来,Rogier和Chauvaud发现,如果忽略了检验和,那样就将产生MD2冲突。MD2算法的加密后结果是唯一的---即没有重复。到MD4完整版本中的冲突(这个冲突实际上是一种漏洞,它将导致对不同的内容进行加密却可能得到相同的加密后结果),毫无疑问,MD4就此被淘汰掉了。

一年以后,即1991年,Rivest开发出技术上更为趋近成熟的MD5算法。它在MD4的基础上增加了“安全-带子”(safety-belts)的概念。虽然MD5比MD4稍微慢一些,但却更为安全。这个算法很明显的由四个和MD4设计有少许不同的步骤组成。在MD5算法中,信息--摘要的大小和填充的必要条件与MD4完全相同。Den Boer和Bosselaers曾发现MD5算法中的假冲突(pseudo-collisions),但除此之外就没有其他被发现的加密后结果了。Van Oorschot和Wiener曾经考虑过一个在散列中暴力搜寻冲突的函数(brute-force
hash function),而且他们猜测一个被设计专门用来搜索MD5冲突的机器可以平均每24天就找到一个冲突,但单从1991年到2001年这10年间,竟没有出现替代MD5算法的新算法,我们可以看出这个瑕疵并没有太多的影响MD5的安全性。而所有这些都不足以成为MD5在实际应用中的问题,并且由于MD5算法的使用不需要支付任何版权费用,所以在一般的情况下,MD5可以算是比较安全的了。

2 相关理论基础

2.1 单向散列函数

单向散列函数[4]也称Hash(哈希)函数。它是现代密码学的核心。散列函数一直在计算机科学中使用,散列函数就是把可变的输入长度串转换成固定长度输出值(叫做散列值)的一种函数。而单向散列函数是在一个方向上工作的散列函数,从预映射的值很容易计算出它的散列值,但要使它的散列值等于一个特殊值却很难。

散列函数是公开的,对处理过程并不保密,单向散列函数的安全性是它的单向性,其输出不依赖于输入。平均而言,预映射值的单个位的改变,将引起散列值中一半位的改变。已知一个散列值,要找到预映射的值,使它的值等于已知的散列值在计算上是不可行的,可把单向散列函数看作是构成指纹文件的一种方法。如果你验证某人持有一个特定的文件(你同时也持有该文件),但你不想他将文件传给你,那么,就要通知他将该文件的散列值传给你,如果他传送的散列值是正确的,那么可以肯定他持有那份文件。

2.1.1 单向散列函数的基本原理

单向散列函数H(M)是对一个任意长度的消息M进行运算。返回一个固定长度的值h。

h=H(M)

其中h的长度为m。

输入为任意长度且输出为固定长度的函数有很多种,但意向散列函数具有使其单向的如下特性:

1)给定值M,可以很方便地计算出h值。

2)给定h,根据H (M) =h计算M很难。

3)给定M,要找到另一则消息M'并使得H(m)=H(m')很难。

也就是说,如果某个入侵者想要获得一则消息,他必须破坏掉每个运用单向函数的协议的安全性,因为单向性函数的关键在于产生M的一个唯一的消息摘要。

事实上,单向散列函数是建立在压缩函数的思想基础之上的。单向散列函数的输出值为一个长度为n的散列值,该长度比输入值的长度m要小很多,即n<m。

进行该函数运算的前提条件是我们应根据一定规则将消息分成若干个消息片段,散列函数的输入值是一个消息片段和前一个消息片段的输出值,而其输出值则是该消息片段前所有消息片段的散列值。这也就是说,消息片段M的散列值的计算方法可表示为:






该过程可图示如下:






同时该散列值又将作为下一步运算的输入值之一,由此推算可知,整个消息的散列值n即为最后一个消息片段经计算所得的散列值。这样,我们最终得到的将是一个固定长度的函数值。

2.1.2 散列值的长度

我们都知道,散列值越长则安全性越好,MD5算法就是单向散列函数产生128位的散列值,以此保证了它的安全性,以下即为生成一个长散列值的方法:

1)运用单向散列函数生成一则消息的散列值。

2)将该散列值附于消息之后。

3)产生包含散列值和消息在内的一连串的数值的散列值。

4)将第一步产生的散列值与第三步产生的散列值组合起来生成一个更大的散列值。

5)重复1)至3)步若干次。

jdk自带算法实现,java调用代码如下:

public class Md5Util {
	public static String md5(String source){
		String des = "";
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] result = md.digest(source.getBytes());
			StringBuilder buf = new StringBuilder();
			for (int i=0;i<result.length;i++) {
				byte b = result[i];
				buf.append(String.format("%02X", b));
			}
			des = buf.toString().toLowerCase();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("md5 failure");
		}
		return des;
	}
	public static void main(String[] args) {
		System.out.println(Md5Util.md5("157701"));
	}
}


参考文档:
http://wenku.baidu.com/link?url=VFEfTG5U8_wpIynHtjeZhJgEZFymj3TdHpNtgFBU2wYt5wU11G1olzAOOmSj6HiyiBhBz04LovuDOV5YeEo5CPNxq-XGo08ctErx7jX9ZLq
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: