MD5算法中的加盐(salt)

  1. java中的简单实例


  2. package com.zving.framework.security;  
  3.   
  4. import java.security.MessageDigest;  
  5. import java.util.Random;  
  6.   
  7. import org.apache.commons.codec.binary.Hex;  
  8.   
  9. public class PasswordUtil {  
  10.     /** 
  11.      * 生成含有随机盐的密码 
  12.      */  
  13.     public static String generate(String password) {  
  14.         Random r = new Random();  
  15.         StringBuilder sb = new StringBuilder(16);  
  16.         sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));  
  17.         int len = sb.length();  
  18.         if (len < 16) {  
  19.             for (int i = 0; i < 16 - len; i++) {  
  20.                 sb.append("0");  
  21.             }  
  22.         }  
  23.         String salt = sb.toString();  
  24.         password = md5Hex(password + salt);  
  25.         char[] cs = new char[48];  
  26.         for (int i = 0; i < 48; i += 3) {  
  27.             cs[i] = password.charAt(i / 3 * 2);  
  28.             char c = salt.charAt(i / 3);  
  29.             cs[i + 1] = c;  
  30.             cs[i + 2] = password.charAt(i / 3 * 2 + 1);  
  31.         }  
  32.         return new String(cs);  
  33.     }  
  34.   
  35.     /** 
  36.      * 校验密码是否正确 
  37.      */  
  38.     public static boolean verify(String password, String md5) {  
  39.         char[] cs1 = new char[32];  
  40.         char[] cs2 = new char[16];  
  41.         for (int i = 0; i < 48; i += 3) {  
  42.             cs1[i / 3 * 2] = md5.charAt(i);  
  43.             cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);  
  44.             cs2[i / 3] = md5.charAt(i + 1);  
  45.         }  
  46.         String salt = new String(cs2);  
  47.         return md5Hex(password + salt).equals(new String(cs1));  
  48.     }  
  49.   
  50.     /** 
  51.      * 获取十六进制字符串形式的MD5摘要 
  52.      */  
  53.     public static String md5Hex(String src) {  
  54.         try {  
  55.             MessageDigest md5 = MessageDigest.getInstance("MD5");  
  56.             byte[] bs = md5.digest(src.getBytes());  
  57.             return new String(new Hex().encode(bs));  
  58.         } catch (Exception e) {  
  59.             return null;  
  60.         }  
  61.     }  
  62.   
  63.     public static void main(String[] args) {  
  64.         String password = generate("admin");  
  65.         System.out.println(verify("admin", password));  
  66.     }  




下面详细介绍一下加Salt散列的过程。介绍之前先强调一点,验证密码时要使用和最初散列密码时使用“相同的”佐料。所以Salt值是要存放在数据库里的。

用户注册时,

  1. 用户输入【账号】和【密码】(以及其他用户信息);
  2. 系统为用户生成【Salt值】;
  3. 系统将【Salt值】和【用户密码】连接到一起;
  4. 对连接后的值进行散列,得到【Hash值】;
  5. 将【Hash值1】和【Salt值】分别放到数据库中。

用户登录时,

  1. 用户输入【账号】和【密码】;
  2. 系统通过用户名找到与之对应的【Hash值】和【Salt值】;
  3. 系统将【Salt值】和【用户输入的密码】连接到一起;
  4. 对连接后的值进行散列,得到【Hash值2】(注意是即时运算出来的值);
  5. 比较【Hash值1】和【Hash值2】是否相等,相等则表示密码正确,否则表示密码错误。

有时候,为了减轻开发压力,程序员会统一使用一个salt值(储存在某个地方),而不是每个用户都生成私有的salt值。



1. 什么是加盐值?
为了加强MD5的安全性(本身是不可逆的),从而加入了新的算法部分即加盐值,加盐值是随机生成的一组字符串,可以包括随机的大小写字母、数字、字符,位数可以根据要求而不一样,使用不同的加盐值产生的最终密文是不一样的。

2. 代码中如何使用加盐值?
由于使用加盐值以后的密码相当的安全,即便是你获得了其中的salt和最终密文,破解也是一个耗费相当多时间的过程,可以说是破解单纯MD5的好几倍,那么使用加盐值以后的密文是如何产生的呢?
1).首先我们得到的是明文的hash值
2).进行计算获取MD5明文hash值
3).随机生成加盐值并插入
4).MD5插入加盐值得到的hash
5).得到最终的密文

3. 如何破解出带有加盐值的密文
因为像windows hash(未进行syskey加密)、非加盐值MD5等都可以通过大型的密码(如彩虹表)表进行对比解密,所以相对而言相当的轻松,而带有加盐值的密文就相对而言复杂的多,现在的MD5表大概是260+G,如何加盐值的可能性有10000个,那么密码表的应该是MD5 size*10000,就可以解密出原MD5表能够解密的密码了,一些网站也提供了对应的salt解密,但是测试以后效果并不是非常好,如常规的admin888也未解密出,实在是遗憾,毕竟MD5本是不可逆的,带入随机值解密出最终密码的可能性就更低了,至少是相对大多数人而言的。

4. 含加盐值MD5算法的应用
目前多家的网站程序公司都已经加入了该算法,如常见的VBB论坛、discuz论坛等都采用了,甚至著名的Linux开源操作系统早已经加入了这种加密模式。可得而知,这种算法势必会在未来应用于更多的范围。

你可能感兴趣的:(java,web)