关于MD5的个性化使用--如何避免解密者通过MD5网站服务对MD5解密

关于MD5的使用
熟悉密码的朋友应该对MD5不陌生,它是一个单项函数,其实MD5的理论基础并不是很实在,它是建立在一个还未解决的数学难题上的,简单的说如果这个数学难题解决了,MD5也就破解了。

我曾经多次将一个MD5加密的密文它通过互联网的MD5解密服务轻松的得到密码,其实这些网站并不是真的把MD5破解了,而是利用建立数据库来建立了一个MD5到明文的映射,这个数据库管理着很多MD5加密的摘要和对应的明文。所以凡是这个数据库里有的密码都是不安全的。所以说MD5是一种树大招风的算法。

难道我们真的要放弃MD5吗?当然不是,任何东西都不能照搬理论,对于现在的这种情况,我们要有我们创新思维,如何正确的使用MD5是一个值得讨论的问题。

对于如何避免解密者通过MD5网站服务对MD5解密,下面给出了几个办法。

第一个方法是使用多重MD5加密,也就是将得到的MD5摘要在做几次。不过这个办法在有些做的比较好的MD5破解网站也有相应的破解方法,所以也不能保证100%有效,但是一般做到3重以上的时候就有效果了。

其代java码如下

import java.security.*;
import java.io.*;
import java.util.*;
import sun.misc.BASE64Encoder;
public class MD5
{
public static String creatPassword(String password)throws Exception
{


MessageDigest md = MessageDigest.getInstance("MD5");

md.update(password.getBytes("UTF8"));
byte[] digest = md.digest();
/*在这里随便做点什么变换就可以了,可以自由发挥了,你也可以写一个反转什么的,我这里就简单点写了,注意为了保证md5的碰撞困难,最好不要改变原有的字符集,就是说最好只交换某些字符的位置,不要改变原有的值
还有你在验证的时候也要按照你发挥的方法写*/
byte tt=digest[0];digest[0]=digest[7];digest[7]=tt;

String outp;
outp = new BASE64Encoder().encode(digest);
/*顺便说一下采用BASE64Encoder编码后原本是16位的字符变成了24位,其中前22位是有效位,不是我们常见的16位了
这里也和我们用的数据库破解也不同,变换的过程其实是吧8位的byte只取6位,然后通过加字符长度来实现*/
return outp;
}
public static void main(String args[])throws Exception{
String md=new MD5().creatPassword("message for test");
System.out.println(md);

}

}
第二个办法就是使用个性化的MD5,个性化是指可以由自己对MD5做一点改进,这也是很好的一种办法,比如你通过MD5得到的摘要在加上自己的一点点小变化,如交换某几个字符的位置,如何交换可以自己发挥了,也做一次反转什么的。但是有一点要指出的是做变换的时候最好不要改变摘要中的字符集。就是说原由的所有字符在改变后都还在,只是位置不同,这样做的目的是不降低MD5的碰撞性。

看了上面两个方法,大家一定能受到启发,在计算机学科里面如果某个问题提出了两种或以上的解决方案的话,一般都会衍生出更多的方法。在这里,我们结合一下以上的办法结合的时候我们可以还进行进一步的变换。首先我们做一个个性化的MD5,我们称PMD5,用PMD5加密一段信息,得到摘要D。然后将摘要D分成左右两部分,将的到的左右两部分再分别做PMD5。然后再对他们通过MD5整合。这样实现起来就比较安全了。

还有的办法就是可以通过随机盐来增加安全性。对同样一段密文加密的两次结果是不一样的,但是又同样能做登录认证,这样就没办法做数据库去匹配了,有兴趣的话可以研究一下,还有,加密结果是40位 ,这种办法为就不多说了。代码如下,熟悉java的朋友应该很容易看明白。

import java.security.*;
import java.io.*;
import java.util.*;
import sun.misc.*;
public class MD
{
//加密
public static String creatPassword(String password)throws Exception
{
SecureRandom random = new SecureRandom();
byte[] salt = new byte[12];
random.nextBytes(salt);
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(salt);
md.update(password.getBytes("UTF8"));
byte[] digest = md.digest();
String outp=new BASE64Encoder().encode(salt);
outp = outp + new BASE64Encoder().encode(digest);
return outp;
}
//认证,gavingPassword是客户输入的密码明文,password是存放的密码的密文
public static boolean authenticatePassword(String gavingPassword,String password ) throws Exception
{
String saltString = password.substring(0,16);
byte[] salt = new BASE64Decoder().decodeBuffer(saltString);
String digest1=password.substring(16);
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(salt);
md.update(gavingPassword.getBytes("UTF8"));
byte[] digest = md.digest();
String digest2 = new BASE64Encoder().encode(digest);
if(digest1.equals(digest2)) return true;
else return false;
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值