PBKDF2算法

应用场景:生成基于口令的密钥(登陆密码的加密)

PBKDF2需要以下的输入:

1.哈希算法

2.密码

3.盐值

4.迭代次数

其中:哈希算法:建议使用SHA256或更安全的算法

           密码:用户的输入值

           盐值:建议最少8个字节,应使用安全的随机数

           迭代次数:建议迭代10000次左右,对于性能有特殊要求的可迭代1000次

           ****PBKDF2算法还有dk_len参数(),通常用不到,本文省略。

下面给出Java的演示代码:


package com.hwj.util;

 

import org.springframework.stereotype.Component;

 

import javax.crypto.SecretKeyFactory;

import javax.crypto.spec.PBEKeySpec;

import java.math.BigInteger;

import java.security.NoSuchAlgorithmException;

import java.security.SecureRandom;

import java.security.spec.InvalidKeySpecException;

import java.security.spec.KeySpec;

 

@Component

public class PBKDF2Util {

 

    public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";

 

    public static final int SALT_BYTE_SIZE = 32 / 2;         //盐的长度

    public static final int HASH_BIT_SIZE = 128 * 4;         //生成密文的长度

    public static final int PBKDF2_ITERATIONS = 1000;        //迭代次数

 


    /**

     * @auther: Ragty

     * @describe: 对输入的密码进行验证

     * @param: [attemptedPassword(待验证密码), encryptedPassword(密文), salt(盐值)](前端传回来的东西)

     * @return: boolean

     * @date: 2018/11/2

     */

    public boolean authenticate(String attemptedPassword, String encryptedPassword, String salt)

            throws NoSuchAlgorithmException, InvalidKeySpecException {

        // 用相同的盐值对用户输入的密码进行加密

        String encryptedAttemptedPassword = getEncryptedPassword(attemptedPassword, salt);

        // 把加密后的密文和原密文进行比较,相同则验证成功,否则失败

        return encryptedAttemptedPassword.equals(encryptedPassword);

    }



    /**

     * @auther: Ragty

     * @describe: 生成密文

     * @param: [password(明文密码), salt(盐值)]

     * @return: java.lang.String

     * @date: 2018/11/2

     */

    public String getEncryptedPassword(String password, String salt) throws NoSuchAlgorithmException,

            InvalidKeySpecException {

 

        KeySpec spec = new PBEKeySpec(password.toCharArray(), fromHex(salt), PBKDF2_ITERATIONS, HASH_BIT_SIZE);

        SecretKeyFactory f = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);

        return toHex(f.generateSecret(spec).getEncoded());

    }

 
    /**

     * @auther: Ragty

     * @describe: 通过加密的强随机数生成盐(最后转换为16进制)

     * @param: []

     * @return: java.lang.String

     * @date: 2018/11/2

     */

    public String generateSalt() throws NoSuchAlgorithmException {

        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");

        byte[] salt = new byte[SALT_BYTE_SIZE];

        random.nextBytes(salt);

 

        return toHex(salt);

    }

 

    /**

     * @auther: Ragty

     * @describe: 十六进制字符串转二进制字符串

     * @param: [hex]

     * @return: byte[]

     * @date: 2018/11/2

     */

    private static byte[] fromHex(String hex) {

        byte[] binary = new byte[hex.length() / 2];

        for (int i = 0; i < binary.length; i++) {

            binary[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);

        }

        return binary;

    }



    /**

     * @auther: Ragty

     * @describe: 二进制字符串转十六进制字符串

     * @param: [array]

     * @return: java.lang.String

     * @date: 2018/11/2

     */

    private static String toHex(byte[] array) {

        BigInteger bi = new BigInteger(1, array);

        String hex = bi.toString(16);

        int paddingLength = (array.length * 2) - hex.length();

        if (paddingLength > 0)

            return String.format("%0" + paddingLength + "d", 0) + hex;

        else

            return hex;

    }

}

因为是结合web项目做,所以不用写主java类【大致不可逆算法流程都是如此,只是细节处理不同】

你可能感兴趣的:(Web)