MD5加盐加密
通常情况下经过散列处理(如MD5)后,会生成一串散列码,这个过程是不可逆的,即无法通过散列后的内容反推出原始内容。但是有些密码因为位数太少而很容易被黑客从彩虹表中直接找到对应的原始内容。因此在散列的时候我们可以主动给用户的密码加上一点随机的东西,让密码长度加长,这样散列出的值基本上是不可能会出现在彩虹表中的,所以就算黑客得到了数据库中保存的散列码,也通过一定规则(下面的盐值就是在散列后的码的第 1、4、7 . . .位)从中得到了正确的盐值,也是无法反推出原始的内容是什么,因为彩虹表中基本上是不可能会有穷举出你这个加了随机盐值散列后的。
1
2 3 import org.apache.commons.codec.binary.Hex; 4 5 import java.security.MessageDigest; 6 import java.security.NoSuchAlgorithmException; 7 import java.util.Random; 8 9 public class MD5Util { 10 public static String generate(String password){ 11 Random random = new Random(); 12 StringBuilder sb = new StringBuilder(16); 13 sb.append(random.nextInt(99999999)).append(random.nextInt(99999999)); 14 int len = sb.length(); 15 if (len < 16 ){ 16 for (int i = 0;i< 16-len;i++){ 17 sb.append("0"); 18 } 19 } 20 String salt = sb.toString(); 21 password = md5Hex(password + salt); 22 char[] chars = new char[48]; 23 for (int i=0;i<48;i+=3){ 24 chars[i] = password.charAt(i/3*2); 25 chars[i+1] = salt.charAt(i/3); 26 chars[i+2] = password.charAt(i/3*2 + 1); 27 } 28 return new String(chars); 29 } 30 31 private static String md5Hex(String str){ 32 try { 33 MessageDigest md5 = MessageDigest.getInstance("MD5"); 34 byte[] bytes = md5.digest(str.getBytes()); 35 return new String(new Hex().encode(bytes)); 36 } catch (NoSuchAlgorithmException e) { 37 e.printStackTrace(); 38 return null; 39 } 40 } 41 42 public static boolean verify(String password,String md5){ 43 char[] char1 = new char[32]; 44 char[] char2 = new char[16]; 45 for (int i=0;i<48;i+=3){ 46 char1[i/3*2] = md5.charAt(i); 47 char1[i/3*2 +1] = md5.charAt(i+2); 48 char2[i/3] = md5.charAt(i + 1); 49 } 50 String salt = new String(char2); 51 return md5Hex(password + salt).equals(new String(char1)); 52 } 53 54 public static void main(String[] args) { 55 String p = MD5Util.generate("abc123"); 56 boolean result = MD5Util.verify("abc123",p); 57 System.out.println(p); 58 System.out.println(result); 59 } 60 }
如有错误,欢迎大家指正,共同进步。