哈希加盐法
背景
由于哈希存在碰撞,当后台数据口被攻击获得用户密码哈希值时,还可以利用彩虹表攻击等方法破解用户密码
加盐
简介
将Hash(p)
变为Hash(p + salt)
,每次计算salt
时随机的,如果要使用彩虹表攻击,必须针对特定的Hash()
重新生成表。
代码实现
// Obtainsalt
package hash;
import java.util.Random;
public class ObtainSalt
{
public static final char[] hex =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
public static String generateRandomSalt()
{
Random random = new Random();
StringBuilder str = new StringBuilder(16);
for (int i = 0; i < str.capacity(); ++i)
{
str.append(hex[random.nextInt(16)]);
}
return str.toString();
}
}
// MD5WithSalt
package hash;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5WithSalt
{
public static String md5WithSalt(String in_str)
{
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
String salt;
salt = ObtainSalt.generateRandomSalt();
String in_with_salt = in_str + salt;
String hash_result = byte2HexStr(md.digest(in_with_salt.getBytes()));
System.out.println("<!-- 加盐密文:" + hash_result + " -->");
// 将盐存储到Hash中,用于登陆验证
char[] result_with_salt = new char[48];
for (int i = 0; i < 48; i += 3)
{
result_with_salt[i] = hash_result.charAt(i / 3 * 2);
result_with_salt[i + 1] = salt.charAt(i / 3); // 每两个Hash字符插入一个salt字符
result_with_salt[i + 2] = hash_result.charAt(i / 3 * 2 + 1);
}
hash_result = new String(result_with_salt);
return hash_result;
}
catch (NoSuchAlgorithmException e)
{
throw new RuntimeException(e);
}
}
public static String byte2HexStr(byte[] bytes)
{
StringBuilder result = new StringBuilder();
for (byte b : bytes)
{
result.append(ObtainSalt.hex[b >>> 4 & 0xF]);
result.append(ObtainSalt.hex[b & 0xF]);
}
return result.toString();
}
}
// MyMD5
import hash.MD5WithSalt;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Scanner;
public class MyMD5
{
public static void main(String[] args) throws NoSuchAlgorithmException
{
Scanner scanner = new Scanner(System.in);
System.out.print("请输入明文:");
String in_str = scanner.next();
System.out.println("明文:" + in_str);
System.out.println("<!-- MD5哈希值:" + md5(in_str) + " -->");
System.out.println("密文:" + MD5WithSalt.md5WithSalt(in_str));
System.out.println();
}
public static String md5(String plain) throws NoSuchAlgorithmException
{
MessageDigest md = MessageDigest.getInstance("MD5");
return MD5WithSalt.byte2HexStr(md.digest(plain.getBytes()));
}
}