加鹽加密的方式
阿新 • • 發佈:2019-01-27
加鹽加密是一種對系統登入口令的加密方式,它實現的方式是將每一個口令同一個叫做”鹽“(salt)的n位隨機數相關聯。無論何時只
要口令改變,隨機數就改變。隨機數以未加密的方式存放在口令檔案中,這樣每個人都可以讀。不再只儲存加密過的口令,而是先將口令和
隨機數連線起來然後一同加密,加密後的結果放在口令檔案中。
import org.apache.commons.codec.binary.Hex;
import java.security.MessageDigest;
/**
* 加鹽加密工具類
*/
public class EncryptedUtil {
/**
* 加鹽字串,長度必須為16位。
*/
private final static String salt = "aaaaaaaaaaaaaa3a";
/**
* 生成含有加鹽的密碼
*/
public static String generate(String password) {
return generate(password, null);
}
/**
* 生成含有加鹽的密碼
*/
public static String generate(String password, String userName) {
String salt = getSalt(userName);
password = md5Hex(password + salt);
char[] cs1 = password.toCharArray();
char[] cs2 = salt.toCharArray();
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = cs1[i / 3 * 2];
cs[i + 1] = cs2[i / 3];
cs[i + 2] = cs1[i / 3 * 2 + 1];
}
return new String(cs).toUpperCase();
}
private static String getSalt(String salt){
if(salt == null || salt.length() == 0){
return EncryptedUtil.salt;
}
if(salt.length() <= 16 ){
return getStringLen8(salt) + EncryptedUtil.salt.substring(7, 15);
} else {
return salt.substring(4, 12) + EncryptedUtil.salt.substring(2, 10);
}
}
public static String getStringLen8(String salt){
if(salt.length() == 8){
return salt;
}
if(salt.length() > 8){
return salt.substring(1, 9);
} else {
return getStringLen8(salt + salt);
}
}
/**
* 校驗密碼是否正確
*/
public static boolean verify(String password, String md5) {
char[] cs = md5.toLowerCase().toCharArray();
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = cs[i];
cs1[i / 3 * 2 + 1] = cs[i + 2];
cs2[i / 3] = cs[i + 1];
}
String salt = new String(cs2);
return md5Hex(password + salt).equals(new String(cs1));
}
/**
* 獲取十六進位制字串形式的MD5摘要
*/
private static String md5Hex(String src) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bs = md5.digest(src.getBytes());
return new String(new Hex().encode(bs));
} catch (Exception e) {
return null;
}
}
}
要口令改變,隨機數就改變。隨機數以未加密的方式存放在口令檔案中,這樣每個人都可以讀。不再只儲存加密過的口令,而是先將口令和
隨機數連線起來然後一同加密,加密後的結果放在口令檔案中。
工具類的實現:
package com.sangame.core.utils;import org.apache.commons.codec.binary.Hex;
import java.security.MessageDigest;
/**
* 加鹽加密工具類
*/
public class EncryptedUtil {
/**
* 加鹽字串,長度必須為16位。
*/
private final static String salt = "aaaaaaaaaaaaaa3a";
/**
* 生成含有加鹽的密碼
*/
public static String generate(String password) {
return generate(password, null);
}
/**
* 生成含有加鹽的密碼
*/
public static String generate(String password, String userName) {
String salt = getSalt(userName);
password = md5Hex(password + salt);
char[] cs1 = password.toCharArray();
char[] cs2 = salt.toCharArray();
char[] cs = new char[48];
for (int i = 0; i < 48; i += 3) {
cs[i] = cs1[i / 3 * 2];
cs[i + 1] = cs2[i / 3];
cs[i + 2] = cs1[i / 3 * 2 + 1];
}
return new String(cs).toUpperCase();
}
private static String getSalt(String salt){
if(salt == null || salt.length() == 0){
return EncryptedUtil.salt;
}
if(salt.length() <= 16 ){
return getStringLen8(salt) + EncryptedUtil.salt.substring(7, 15);
} else {
return salt.substring(4, 12) + EncryptedUtil.salt.substring(2, 10);
}
}
public static String getStringLen8(String salt){
if(salt.length() == 8){
return salt;
}
if(salt.length() > 8){
return salt.substring(1, 9);
} else {
return getStringLen8(salt + salt);
}
}
/**
* 校驗密碼是否正確
*/
public static boolean verify(String password, String md5) {
char[] cs = md5.toLowerCase().toCharArray();
char[] cs1 = new char[32];
char[] cs2 = new char[16];
for (int i = 0; i < 48; i += 3) {
cs1[i / 3 * 2] = cs[i];
cs1[i / 3 * 2 + 1] = cs[i + 2];
cs2[i / 3] = cs[i + 1];
}
String salt = new String(cs2);
return md5Hex(password + salt).equals(new String(cs1));
}
/**
* 獲取十六進位制字串形式的MD5摘要
*/
private static String md5Hex(String src) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
byte[] bs = md5.digest(src.getBytes());
return new String(new Hex().encode(bs));
} catch (Exception e) {
return null;
}
}
}