0
点赞
收藏
分享

微信扫一扫

针对django的check_password()方法用java编写类似的验证

九点韶留学 2022-03-22 阅读 58
javapython

业务需要到记录一下,直接上代码


import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
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;

/**
 * @author :smallkinghjm
 * @description:因为需要和django的的系统兼容,这里模拟django的check_password()方法实现对用户密码的加密及验证,只保证验证成功的版本
 * jdk:1.8
 * 加密算法:pbkdf2_sha256
 * @date :2022/3/4 13:19
 */
@Slf4j
public class CryptoUtil {

    private static Integer DEFAULT_ITERATIONS = 20000;//默认迭代次数
    public static String algorithm = "pbkdf2_sha256";

    private static String getEncodedHash(String password, String salt, int iterations) {

        // 仅返回整个编码密码的最后一部分
        SecretKeyFactory keyFactory = null;
        try {
            keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        } catch (NoSuchAlgorithmException e) {
            log.info("无法检索PBKDF2WithHmacSHA256算法!!!");
        }

        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) {
            log.info("无法生成密钥");
            e.printStackTrace();
        }

        byte[] rawHash = secret.getEncoded();
        byte[] hashBase64 = Base64.getEncoder().encode(rawHash);

        return new String(hashBase64);
    }

    /**
     * 加盐
     * @return
     */
    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);
    }


    public static String encode(String password) {
        return encode(password, getSalt());
    }

    private static String encode(String password,int iterations) {
        return encode(password, getSalt(),iterations);
    }

    private static String encode(String password, String salt) {
        return encode(password, salt, DEFAULT_ITERATIONS);
    }
    /**
     *
     * @param password
     * @param salt
     * @param iterations
     * @return
     */
    private static String encode(String password, String salt, int iterations) {
        // 返回哈希密码,以及算法、迭代次数和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 checkPassword(String password, String hashedPassword) {

        /*
        <algorithm>$<iterations>$<salt>$<hash>
        以美元字符分分隔并由哈希算法、算法迭代次数(工作因数)、随机的salt、以及生成的密码哈希值组成
         */

        String[] parts = hashedPassword.split("\\$");
        if (parts.length != 4) {
            //格式错误
            return false;
        }

        Integer iterations = Integer.parseInt(parts[1]);
        String salt = parts[2];
        String hash = encode(password, salt, iterations);

        return hash.equals(hashedPassword);
    }

    public static void main(String[] args) {
        String encode = encode("Admin@2022");
        System.out.println("后端加密:"+encode);

        boolean check = checkPassword("Admin@2022", "pbkdf2_sha256$20000$T7314mPWi61g$pfswjCjI+geqU4bcTmhYe4mHp116eWuVxl35Si42Plk=");
        System.out.println("密码校验结果:"+check);
    }
}

参考:
java实现Django的PBKDF2PasswordHasher加密算法

举报

相关推荐

0 条评论