在系统中密码通常需要以密文的形式来存储到系统中去,所以在操作过程中通常需要将明文的密码加密。
加密的方式可以分为:双向加密 单向加密。
由于一般的加密后方式很容器破解,如对于MD5加密来说攻击者只需要一个简单的sql语句
`:select * from userInfo where password=’4QrcOUm6Wau+VuBX8g+IPg==’
` 就可以知道有几个用户密码是”123456”,这对一个项目来说十分危险。所以一般在加密之前,配上一个一串的随机序列。称之为salt。
盐是一个添加到用户的密码哈希过程中的一段随机序列。这个机制能够防止通过预先计算结果的彩虹表破解。每个用户都有自己的盐,这样的结果就是即使用户的密码相同,通过加盐后哈希值也将不同。然而,在将盐与密文存储的位置上有很多矛盾的地方,有的时候将两者存在一起比较方便,有的时候为了安全考虑又不得不将两者分开存储。由于PBKDF2算法通过key的机制避免了暴力破解,我觉得没必要将盐隐藏起来,就跟密文存储在同一个位置。
本文主要分享一个PBKDF2加密的工具类,如下。
public static final int HASH_MILLIS = 1231;
public static final String ALGORITHM = "asfdasdfdfsafs";
public static final int ITERATION_COUNT = 123123;
public static final int KEY_SIZE = 123;
public static final int SALT_LENGTH = 123;
/**
*
* @Title: getSalt
* @author:陈方林
* @Description: TODO(得到salt)
* @param @return 设定文件
* @return String 返回类型
* @date 上午9:28:18
*/
public static String getSalt(){
String salt=new String(Base64.encodeBase64(nextSalt()));
return salt;
}
/**
*
* @author:cfl
* @Description: TODO(密码加密)
* @param @param salt
* @param @param password 明文
* @param @return 加盐后的密文
* @param @throws Exception 设定文件
* @return String 返回类型
* @date 2015年7月20日18:36:21
*/
public static String encryptPassword(String salt,String password) throws Exception{
byte[] saltByte = Base64.decodeBase64(salt.getBytes());
byte[] hash = PasswordsUtils.hashPassword(password.toCharArray(), saltByte);
String pwd_hash_str = new String(Base64.encodeBase64(hash));
return pwd_hash_str;
}
public static byte[] hashPassword(char[] password, byte[] salt)
throws GeneralSecurityException {
return hashPassword(password, salt, ITERATION_COUNT, KEY_SIZE);
}
public static byte[] hashPassword(char[] password, byte[] salt,
int iterationCount, int keySize) throws GeneralSecurityException {
try {
PBEKeySpec spec = new PBEKeySpec(password, salt, iterationCount, keySize);
SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);
return factory.generateSecret(spec).getEncoded();
} catch (IllegalArgumentException e) {
throw new GeneralSecurityException("key size " + keySize, e);
}
}
public static boolean matches(char[] password, byte[] passwordHash, byte[] salt)
throws GeneralSecurityException {
return matches(password, passwordHash, salt, ITERATION_COUNT, KEY_SIZE);
}
public static boolean matches(char[] password, byte[] passwordHash, byte[] salt,
int iterationCount, int keySize) throws GeneralSecurityException {
return Arrays.equals(passwordHash, hashPassword(password, salt,
iterationCount, keySize));
}
public static byte[] nextSalt() {
byte[] salt = new byte[SALT_LENGTH];
SecureRandom sr = new SecureRandom();
sr.nextBytes(salt);
return salt;
}
验证示例
UserInfo userinfo=SessionManager.getLoginUser();
String salt=userinfo.getSalt();
String realPassword=userinfo.getPassword();
String inputPassword; //用户输入的password
//返回用户输入密码加密后的密文
String encryptPassword=PasswordsUtils.encryptPassword(salt, inputPassword);
if(encryptPassword.equals(realPassword)){
return true;
}else{
return false;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/cfl20121314/article/details/46994393