Java 为什么我的PBKDF2散列方法返回不同的输出?

Java 为什么我的PBKDF2散列方法返回不同的输出?,java,hash,salt,pbkdf2,Java,Hash,Salt,Pbkdf2,我为我的密码学初学者水平道歉。 在我的项目中,我发现在将密码插入数据库之前需要对密码进行散列,因此我搜索了顶级散列算法,发现了PBKFD2和salt方法 我这样做的方法是生成随机64char Salt并使用它来散列密码。然后将哈希密码和salt存储在我的数据库中。(注:注册时也会生成密码。这不是我的选择) 登录时,我的Servlet获取密码,然后用数据库中存储的salt散列它。但我得到了不同的结果 这是我的密码 public static String generatePassword() {

我为我的密码学初学者水平道歉。
在我的项目中,我发现在将密码插入数据库之前需要对密码进行散列,因此我搜索了顶级散列算法,发现了PBKFD2和salt方法

我这样做的方法是生成随机64char Salt并使用它来散列密码。然后将哈希密码和salt存储在我的数据库中。(注:注册时也会生成密码。这不是我的选择)

登录时,我的Servlet获取密码,然后用数据库中存储的salt散列它。但我得到了不同的结果 这是我的密码

 public static String generatePassword() {
          CharacterRule alphabets = new CharacterRule(EnglishCharacterData.Alphabetical);
          CharacterRule digits = new CharacterRule(EnglishCharacterData.Digit);
          

          PasswordGenerator passwordGenerator = new PasswordGenerator();
          String password = passwordGenerator.generatePassword(10, alphabets, digits);
          return password ; 
       }
       
       
       public static byte[] hashPassword( final char[] password, final byte[] salt, final int iterations, final int keyLength ) throws UnsupportedEncodingException {

            try {
                SecretKeyFactory skf = SecretKeyFactory.getInstance( "PBKDF2WithHmacSHA512" );
                PBEKeySpec spec = new PBEKeySpec( password, salt, iterations, keyLength );
                SecretKey key = skf.generateSecret( spec );
                byte[] res = key.getEncoded( );
                return res;
            } catch ( NoSuchAlgorithmException | InvalidKeySpecException e ) {
                throw new RuntimeException( e );
            }
        }
       
       public static HashMap<Integer,String> hashGeneeratedPassword(String password) throws UnsupportedEncodingException {
            HashMap<Integer,String> returnValues = new HashMap<Integer,String>() ; 
            int iterations = 20000;
            int keyLength = 512;
            char[] passwordChars = password.toCharArray();
            byte[] saltBytes = generateSalt() ; 

            byte[] hashedBytes = hashPassword(passwordChars, saltBytes, iterations, keyLength);
            String hashedString = HexUtils.toHexString(hashedBytes); 
            String saltString = HexUtils.toHexString(saltBytes) ;
            
            returnValues.put(1,hashedString); 
            returnValues.put(2, saltString);
            
            return returnValues ; 
        }
       
       private static byte[] generateSalt() {
            SecureRandom random = new SecureRandom();
            byte[] salt = new byte[32];
            random.nextBytes(salt);
            return salt;
        }
       
       public static String hashLoginPassword(String password,String salt) throws UnsupportedEncodingException {
            
            int iterations = 20000;
            int keyLength = 512;
            char[] passwordChars = password.toCharArray();
            byte[] saltBytes = salt.getBytes();

            byte[] hashedBytes = hashPassword(passwordChars, saltBytes, iterations, keyLength);
            String hashedString = HexUtils.toHexString(hashedBytes); 

            return hashedString ; 
        }
public静态字符串generatePassword(){
CharacterRule alphabets=新的CharacterRule(EnglishCharacterData.Alphabeth);
CharacterRule digits=新的CharacterRule(EnglishCharacterData.Digit);
PasswordGenerator PasswordGenerator=新的PasswordGenerator();
字符串密码=passwordGenerator.generatePassword(10,字母,数字);
返回密码;
}
公共静态字节[]hashPassword(最终字符[]密码,最终字节[]salt,最终整数迭代,最终整数keyLength)引发UnsupportedEncodingException{
试一试{
SecretKeyFactory skf=SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA512”);
PBEKeySpec spec=新的PBEKeySpec(密码、salt、迭代次数、密钥长度);
SecretKey=skf.generateSecret(规范);
字节[]res=key.getEncoded();
返回res;
}捕获(NoSuchAlgorithmException | InvalidKeySpece异常){
抛出新的运行时异常(e);
}
}
公共静态HashMap HashGeneratedPassword(字符串密码)引发UnsupportedEncodingException{
HashMap returnValues=新的HashMap();
int迭代次数=20000次;
int keyLength=512;
char[]passwordChars=password.tocharray();
字节[]saltBytes=generateSalt();
byte[]hashedBytes=hashPassword(密码字符、saltBytes、迭代次数、keyLength);
String hashedString=HexUtils.toHexString(hashedBytes);
String saltString=HexUtils.toHexString(saltBytes);
returnValues.put(1,hashedString);
returnValues.put(2,saltString);
返回值;
}
专用静态字节[]generateSalt(){
SecureRandom=新的SecureRandom();
字节[]salt=新字节[32];
随机。下一个字节(盐);
返盐;
}
公共静态字符串hashLoginPassword(字符串密码,字符串salt)引发UnsupportedEncodingException{
int迭代次数=20000次;
int keyLength=512;
char[]passwordChars=password.tocharray();
字节[]saltBytes=salt.getBytes();
byte[]hashedBytes=hashPassword(密码字符、saltBytes、迭代次数、keyLength);
String hashedString=HexUtils.toHexString(hashedBytes);
返回hashedString;
}
感谢您抽出时间阅读我的帖子。

解决方案:
我用于转换字节[]salt和字节[]散列的工具出错。我使用了HexUtil,一切都很好。

用户第一次注册(或更改密码)是在您创建salt时。此后,每当用户尝试登录时,您都会从数据库中检索此salt,并与密码一起重新计算散列,然后与存储的散列进行比较以验证用户。你不会为每个登录生成一个全新的随机salt。我知道这一点。这就是我创建hashLoginPassword(密码,salt)的原因。它使用从DB检索的用户自己的salt对用户输入的密码进行哈希运算。Salt仅在注册时由hashGeneratedPassword(字符串密码)生成,该密码返回生成的Salt和哈希值,并存储在my DB中。