java 实现 pbkdf2_sha256加密验证算法

Wesley13
• 阅读 282
import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Base64;
import java.util.Random;

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

/**
 * pbkdf2_sha256加密验证算法
 * @author Administrator
 *
 */
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Pbkdf2Sha256 {

    private static final Logger logger=LoggerFactory.getLogger(Pbkdf2Sha256.class);
    //默认迭代计数为 20000
    private static final Integer DEFAULT_ITERATIONS = 20000;
    //算法名称
    private static final String algorithm = "pbkdf2_sha256";

    /**
     * 获取密文
     * @param password 密码明文
     * @param salt 加盐
     * @param iterations 迭代计数
     * @return
     */
    private static String getEncodedHash(String password, String salt, int iterations) {
        // Returns only the last part of whole encoded password
        SecretKeyFactory keyFactory = null;
        try {
            keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        } catch (NoSuchAlgorithmException e) {
            logger.error("Could NOT retrieve PBKDF2WithHmacSHA256 algorithm",e);
        }
        KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt.getBytes(Charset.forName("UTF-8")), iterations, 256);
        SecretKey secret = null;
        try {
            secret = keyFactory.generateSecret(keySpec);
        } catch (InvalidKeySpecException e) {
            logger.error("Could NOT generate secret key",e);
        }
        byte[] rawHash = secret.getEncoded();
        byte[] hashBase64 = Base64.getEncoder().encode(rawHash);

        return new String(hashBase64);
    }
    /**
     * 密文加盐
     * @return String
     */
    private static String getsalt(){
        int length = 12;
        Random rand = new Random();
                char[] rs = new char[length];
                    for(int i = 0; i < length; i++){
                    int t = rand.nextInt(3);
                    if (t == 0) {
                        rs[i] = (char)(rand.nextInt(10)+48);
                    } else if (t == 1) {
                         rs[i] = (char)(rand.nextInt(26)+65);
                    } else {
                        rs[i] = (char)(rand.nextInt(26)+97);
                    }
                }
                return new String(rs);
    }
    /**
     * rand salt
     * iterations is default 20000
     * @param password
     * @return
     */
    public static String encode(String password) {
        return encode(password, getsalt());
    }
    /**
     * rand salt
     * @param password
     * @return
     */
    public static String encode(String password,int iterations) {
        return encode(password, getsalt(),iterations);
    }
    /**
     * iterations is default 20000
     * @param password
     * @param salt
     * @return
     */
    public static String encode(String password, String salt) {
        return encode(password, salt, DEFAULT_ITERATIONS);
    }
    
    /**
     * 
     * @param password 密码明文
     * @param salt 加盐
     * @param iterations 迭代计数
     * @return
     */
    public static String encode(String password, String salt, int iterations) {
        // returns hashed password, along with algorithm, number of iterations and salt
        String hash = getEncodedHash(password, salt, iterations);
        return String.format("%s$%d$%s$%s", algorithm, iterations, salt, hash);
    }

    /**
     * 校验密码是否合法
     * @param password 明文
     * @param hashedPassword 密文
     * @return
     */
    public static boolean verification(String password, String hashedPassword) {
        // hashedPassword consist of: ALGORITHM, ITERATIONS_NUMBER, SALT and
        // HASH; parts are joined with dollar character ("$")
        String[] parts = hashedPassword.split("\\$");
        if (parts.length != 4) {
            // wrong hash format
            return false;
        }
        Integer iterations = Integer.parseInt(parts[1]);
        String salt = parts[2];
        String hash = encode(password, salt, iterations);
        return hash.equals(hashedPassword);
    }
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
QQ音乐API分析之
QQ音乐API加密参数分析1、背景2、QQ音乐sign计算3、Java代码实现4、总结1、背景不知道什么时候开始,各家音乐APP都开始对API进行加密,最近一段时间对六大音乐平台的加密算法进行了研究,逆向了网页端、安卓端等等,已经掌握了各家的加密算法。平台加密算法非加密接口专
Wesley13 Wesley13
2年前
java实现SHA1加密算法
packageutil;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;publicclassSha1{   publicstaticStringSHA1(Stringdecript){
Wesley13 Wesley13
2年前
JAVA加密算法(1)
密码学综述密码学基本功能机密性、鉴别、报文完整性、不可否认性基本模型sender加密算法密文解密算法receiver密钥源密码学算法分类:消息编码:Base64消息摘要:MD类,SHA类,MAC对称加密:DES,3DES,AES
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
2年前
Java日期时间API系列35
  通过Java日期时间API系列1Jdk7及以前的日期时间类(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2Fxkzhangsanx%2Fp%2F12032719.html)中得知,Java8以前除了java.sql.Timestamp扩充
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
京东云开发者 京东云开发者
6个月前
Java服务总在半夜挂,背后的真相竟然是... | 京东云技术团队
最近有用户反馈测试环境Java服务总在凌晨00:00左右挂掉,用户反馈Java服务没有定时任务,也没有流量突增的情况,Jvm配置也合理,莫名其妙就挂了