【问题标题】:Java's implementation of PBKDF2 with HMAC SHA1 return different hash every time an button is pushed?每次按下按钮时,带有 HMAC SHA1 的 Java PBKDF2 实现返回不同的哈希?
【发布时间】:2016-07-13 11:40:11
【问题描述】:

我创建了一个简单的 GUI,其中包含密码字段、输入按钮和文本区域,以在按下输入按钮时显示生成的密码哈希。但是当我再次按下按钮时,即使输入密码仍然相同,哈希也会改变。我无法将输入的密码与存储的密码进行比较,因为每次输出哈希都会改变。

代码如下:

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public PBKDF2() {
    initComponents();
}

private void initComponents() {//"Generated Code"
...... 
}

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    password= jPasswordField1.getPassword();
    jTextArea1.setText(null);
    try {
        jTextArea1.append(hashPassword(password.toString(), "salt"));
    } catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
        Logger.getLogger(PBKDF2.class.getName()).log(Level.SEVERE, null, ex);
    }
}

public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new PBKDF2().setVisible(true);
            }
        });
    }

 public static String hashPassword(String password, String salt) throws NoSuchAlgorithmException, InvalidKeySpecException{
    char[] pw = password.toCharArray();
    byte[] slt = salt.getBytes(StandardCharsets.UTF_8);
    PBEKeySpec spec = new PBEKeySpec(pw,slt,2000,160);
    SecretKeyFactory key = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    byte[] hashedPassword = key.generateSecret(spec).getEncoded();
    return String.format("%X", new BigInteger(hashedPassword));
  }

    public static char[] password;
    public javax.swing.JButton jButton1;
    public javax.swing.JPasswordField jPasswordField1;
    public javax.swing.JScrollPane jScrollPane1;
    public javax.swing.JTextArea jTextArea1;
}

如果我从 main 方法调用它,它每次只返回相同的哈希值。这是为什么?每次我输入相同的密码并按下按钮时,如何让它返回相同的值?

我认为我在将字符串转换为 chararray 来回时发现了问题。将方法 hashPassword 编辑为 hashPassword(char[] password, String salt) 并让它现在工作。

不知何故,当将 String 转换为 CharArray 时,输出每次都不同。下面是测试代码:

Code:
char[] pw0="password".toCharArray();
char[] pw1="password".toCharArray();

jTextArea1.append("\nCase1: "+hashPassword(pw0.toString(), "salt"));
jTextArea1.append("\nCase2:"+hashPassword(pw1.toString(), "salt"));

Result:        
Case1: -48b7cb730ce85dd46cb2cac6960eb1971f2d30e4
Case2:64765fbdada52d536d89bf2fac72b058397e9ec9

这很奇怪,因为 pw0 和 pw1 等于 "password".toCharArray()。我想知道 String.toCharArray() 中是否有错误??

【问题讨论】:

  • 根据定义,盐渍哈希每次都不同——这是有原因的。为什么你会期望它们是一样的?如果这是你想要的,每次都喂同样的盐。但请不要在生产中这样做。
  • @fge ,相同的盐应该返回相同的哈希值。
  • 从简化问题开始,通过使用 main 方法中的固定值调用 hashPassword 方法来测试它,并将输出打印到 System.out。
  • @A.Grandt 我想我发现了问题:从密码(char)转换为字符串时出错
  • @LukeMartin ,那是另一回事,不要将密码转换为字符串,只需将其保留为您从密码字段中获取的字符数组即可。

标签: java user-interface hash pbkdf2


【解决方案1】:

技术上,你打电话

"abc".toCharArray().toString();

这将导致

[C@abcdef10

因此,每次运行时,您都会得到另一个值。

你应该做的是:

jTextArea1.append("\nCase1: "+hashPassword(new String(pw0), "salt"));
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-01
    • 2011-01-28
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    • 2021-04-11
    • 2013-12-01
    • 1970-01-01
    相关资源
    最近更新 更多