加盐加密是一种对系统登录口令的加密方式,它实现的方式是将每一个口令同一个叫做”盐“(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;
}
}
}
要口令改变,随机数就改变。随机数以未加密的方式存放在口令文件中,这样每个人都可以读。不再只保存加密过的口令,而是先将口令和
随机数连接起来然后一同加密,加密后的结果放在口令文件中。
工具类的实现:
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;
}
}
}