在日常开发中,数据库用户表密码的存放一般不会放置明文密码.就算存的是加密后的,相同密码加密后获得的字符串也是相同的.今天博主学习了一种加密算法,每次生成的密文不同
废话少说,开始coding....
生成随机的Byte[]作为salt
// numBytes为想要生成"盐"的长度
private static byte[] generateSalt(int numBytes) {
byte[] bytes = new byte[numBytes];
new SecureRandom().nextBytes(bytes);
return bytes;
}
HTML 解码
//htmlEscaped 为想要加密的字符串
private static String unescapeHtml(String htmlEscaped) {
return StringEscapeUtils.unescapeHtml4(htmlEscaped);
}
Hex编码
private static String encodeHex(byte[] input) {
return new String(Hex.encodeHex(input));
}
Hex解码
private static byte[] decodeHex(String input) {
byte[] bytes = null;
try {
bytes = Hex.decodeHex(input.toCharArray());
} catch (DecoderException e) {
e.printStackTrace();
}
return bytes;
}
对字符串进行散列(精华部分)
/**
* iterations sha-1的次数
* salt 参与算法的盐
* input 参与算法的字符串.getBytes()
*/
private static byte[] digest(byte[] input, byte[] salt, int iterations) {
MessageDigest digest = null;
try {
//这里也可以MD5
digest = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
if (salt != null) {
digest.update(salt);
}
byte[] result = digest.digest(input);
for (int i = 1; i < iterations; i++) {
digest.reset();
result = digest.digest(result);
}
return result;
}
准备工作完毕,开始进行安全字符串的生成
public static String createSign(String sign) {
//将目标字符串进行处理
String plain = unescapeHtml(sign);
//生成参与算法的盐
byte[] salt = generateSalt(8);
//经过1024次sha-1.
byte[] hashStr = digest(plain.getBytes(),salt,1024);
//返回密文
return encodeHex(salt) + encodeHex(hashStr);
}
由于是单向加密,对生成密文无法解密,所以我们判定方法为将目标字符串再次进行加密看与之前加密过的hash相同与否
/**
* sign 目标字符串
* hashSign 已存在的密文
*/
public static boolean validateSign(String sign, String hashSign) {
String plain = unescapeHtml(sign);
//得到上次上次参与算法的盐
byte[] salt = decodeHex(hashSign.substring(0, 16));
byte[] hashStr = digest(plain.getBytes(), salt,1028);
return hashSign.equals(encodeHex(salt)+ encodeHex(hashStr));
}
我们来验证下:
public static void main(String[] args) {
System.out.println("wisty字符串第一次加密结果:"+createSign("wisty"));
System.out.println("wisty字符串第二次加密结果:"+createSign("wisty"));
System.out.println("wisty字符串第三次加密结果:"+createSign("wisty"));
System.out.println("wisty字符串第四次加密结果:"+createSign("wisty"));
}
------------------结果如下--------------
wisty字符串第一次加密结果:8d4b1d479556a3fea133e7ce663d778d5ad47606ea4d02192e174f46
wisty字符串第二次加密结果:8ed8b6bf9860139679a7161c8afd4ebe4dbef6f951231adbd7757e1c
wisty字符串第三次加密结果:75a1146425ed57067d22332b11f628ee822e725f625b778231c14162
wisty字符串第四次加密结果:21f513cf5e8f793ee3af9b1f210b08803c5bab614fbd543791e6ba29
public static void main(String[] args) {
System.out.println("明密文第一次比较结果:"+validateSign("wisty","8d4b1d479556a3fea133e7ce663d778d5ad47606ea4d02192e174f46"));
System.out.println("明密文第二次比较结果:"+validateSign("wisty","8ed8b6bf9860139679a7161c8afd4ebe4dbef6f951231adbd7757e1c"));
System.out.println("明密文第三次比较结果:"+validateSign("wisty","75a1146425ed57067d22332b11f628ee822e725f625b778231c14162"));
System.out.println("明密文第四次比较结果:"+validateSign("wisty","21f513cf5e8f793ee3af9b1f210b08803c5bab614fbd543791e6ba29"));
------------------结果如下--------------
明密文第一次比较结果:true
明密文第二次比较结果:true
明密文第三次比较结果:true
明密文第四次比较结果:true
从上面我们可以看到每次生成的密文都不同,通过比较密文指向同一个明文………..
欢迎大家交流学习