首页 > 编程语言 > 详细

Java版PBKDF2验证

时间:2015-07-22 00:02:38      阅读:838      评论:0      收藏:0      [点我收藏+]

在系统中密码通常需要以密文的形式来存储到系统中去,所以在操作过程中通常需要将明文的密码加密。

加密的方式可以分为:双向加密 单向加密。

  • 双向加密:简单来理解就是可以通过密钥将加密后的密文解密为明文。常用的加密DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES。
  • 反之,单向加密则为不可逆的加密方式。常见的如:MD5 、SHA 。
    而双向加密中又分为对称加密和非对称加密。这个是根据加密和解密的密钥是否相同来决定的,对称加密则加密和解密的密钥相同,非对象加密则反之。

由于一般的加密后方式很容器破解,如对于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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Java版PBKDF2验证

原文:http://blog.csdn.net/cfl20121314/article/details/46994393

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!