Java 如何将salt与生成的密码进行比较?

Java 如何将salt与生成的密码进行比较?,java,security,servlets,cryptography,salt,Java,Security,Servlets,Cryptography,Salt,所以我试着把我的原始密码和一个加了盐的密码进行比较。我知道如何比较散列密码,我将原始密码添加到散列中,它就工作了。然而,我不知道如何比较盐 public static String saltPassword(String password) throws NoSuchAlgorithmException{ String salt = getSalt(); return password + salt; } public static String getSalt(){

所以我试着把我的原始密码和一个加了盐的密码进行比较。我知道如何比较散列密码,我将原始密码添加到散列中,它就工作了。然而,我不知道如何比较盐

public static String saltPassword(String password) throws NoSuchAlgorithmException{
     String salt = getSalt();
     return password + salt;
 }
public static String getSalt(){
     Random r = new SecureRandom();
     byte[] saltBytes = new byte[32];
     r.nextBytes(saltBytes);
     return Base64.getEncoder().encodeToString(saltBytes);
 }
要将原始密码与此密码进行比较,我需要做什么

我的任务就是这么说的,
“将生成的密码与存储的salt和哈希密码进行比较”。

您还应该存储salt。Salt用于在两个用户选择相同密码时预先生成相同的哈希密码。类似于以下代码的代码可用于将密码保存为hashedPassord并验证输入的密码。它不完整,但可以用作示例代码

private static void savePassword(字符串rawPassword)引发InvalidKeySpecException、NoSuchAlgorithmException{
字节[]salt=getSalt();
字符串hashedPassword=getHashedPassword(rawspassword,salt);
字符串encodedSalt=base64Encode(salt);
/*todo:存储hashPassword和encodedAlt*/
}
私有静态布尔验证密码(String rawPassword、String hashedPassword、String EncodedAlt)引发InvalidKeySpecException、NoSuchAlgorithmException{
返回Objects.equals(hashedPassword、getHashedPassword(rawPassword、base64Decode(encodedSalt));
}
私有静态字符串getHashedPassword(字符串rawPassword,字节[]salt)引发NoSuchAlgorithmException,InvalidKeySpecException{
KeySpec spec=new-PBEKeySpec(rawPassword.tocharray(),salt,65536128);
SecretKeyFactory factory=SecretKeyFactory.getInstance(“PBKDF2WithHmacSHA1”);
byte[]hash=factory.generateScret(spec.getEncoded();
返回base64Encode(散列);
}
私有静态字节[]getSalt(){
Random r=新的SecureRandom();
字节[]saltBytes=新字节[32];
r、 下个字节(saltBytes);
返回saltBytes;
}
专用静态字符串base64Encode(字节[]src){
返回Base64.getEncoder().encodeToString(src);
}
专用静态字节[]base64Decode(字符串src){
返回Base64.getDecoder().decode(src);
}
如何将salt与生成的密码进行比较

要将原始密码与此密码进行比较,我需要做什么

答案是,如果这些事情发生了,你也不会做

要注册原始密码,请执行以下操作:

  • 获得一个salt1
  • 将原始密码与salt组合
  • 胡说
  • 把盐和炸土豆条放好
  • 然后放弃原始密码

    要检查提供的密码是否正确,请执行以下操作:

  • 查找存储的哈希和注册时创建的相应salt;见上文
  • 以与上面相同的方式组合提供的密码和salt
  • 如上所述
  • 将结果哈希与存储的哈希进行比较。如果它们相同,则提供的密码是正确的密码
  • 正如您所看到的,您不会将salt或原始密码与任何东西进行比较

    但是,在为原始密码和正在检查的密码生成哈希值时,使用相同的salt也是至关重要的。如果不这样做,则密码检查不起作用



    盐只是一个数字或字符串。理想情况下,盐值应该不同。salt的目的是避免所谓的从被盗(未加密)的密码散列中恢复原始密码。如果(比如)有一百万个可能的盐值,那么坏人需要生成一百万个不同的彩虹表。生成和存储许多rainbow表变得不切实际。

    好的,这就是我所拥有的。我很想查找存储的密码,但我的老师在她的解决方案视频中没有这样做

    public static String saltPassword(String password) throws NoSuchAlgorithmException{
         String salt = getSalt();
         return hashPassword(password + salt);
     }
     public static String getSalt(){
         Random r = new SecureRandom();
         byte[] saltBytes = new byte[32];
         r.nextBytes(saltBytes);
         return Base64.getEncoder().encodeToString(saltBytes);
     }
     public static String generatePassword(){
            String charSet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-+!@#$%";
            String password = "";
            int start = 0;
            int stop = 0;
            int minLength = 8;
    
            for (int i = 0; i <= minLength; i++) {
                    // get a random character from the chars string
                    start = getRandomNumber(charSet.length());
                    stop = start + 1;
                    password += charSet.substring(start, stop);
            }        
            return password;
        }
        private static int getRandomNumber(int maxValue){
            double randomNumber;
            randomNumber = Math.floor(Math.random() * maxValue);
    
            return (int)randomNumber;
        }
        public static String hashPassword(String password)throws NoSuchAlgorithmException{
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(password.getBytes());
            byte[] mdArray = md.digest();
            StringBuilder sb = new StringBuilder(mdArray.length * 2);
            for (byte b : mdArray){
                int v = b & 0xff;
                if(v < 16){
                    sb.append('0');
                }
                sb.append(Integer.toHexString(v));
            }
            return sb.toString();   
        }
    
    接下来会发生什么

    这是哈希密码:

    50f99d2a635cc9bac7e001506789b55a7c603d93c89d362cc5d95ab257fc2666
    
    这是加盐的肉馅

    e954fbc2309cc359cd603effb6d0644947a3253110ad6c3b2416dd49168331a3
    

    答案是你没有。你把密码和盐放在一起。那你就把它弄碎。然后比较>>哈希值,不管你按什么顺序做。我尝试过类似的方法,但我先是对密码进行哈希运算,然后再添加salt,如何使用与以前相同的salt,因为每次我的答案都是随机的。您(通常)将盐与原始密码的散列一起存储。我会问您同样的问题。我点什么顺序的盐/肉馅重要吗?既然每次都是随机的,我怎么用和以前一样的盐。嗨@studentguy。生成salt应该在散列密码之前完成。如果将生成的盐存储在DB中,则可以在需要时使用相同的盐。我添加了一些示例代码,希望这对您有所帮助。感谢您帮助我获得上面列出的一些代码。我希望这会更有帮助,每次生成一个新的随机盐,而不使用散列存储它是行不通的。很可能您误解了这是如何工作的。我注意到,在您的自我回答中,讲师的代码实际上没有存储任何内容。我倾向于认为讲师搞错了……所以如果一个随机的salt不可比较,那么为什么要存储它呢?我不理解你的评论。我没有说salt是可比较的。我说的是,在生成原始密码的散列和你输入的密码的散列时,必须使用相同的salt我想查查。这就是为什么你必须储存原盐。。。或者从其他(恒定)信息(例如用户的帐户名)生成salt
    e954fbc2309cc359cd603effb6d0644947a3253110ad6c3b2416dd49168331a3