【问题标题】:User Authentication in Java using 128-bit AES encryption in CBC mode with PKCS #5 padding在 CBC 模式下使用 128 位 AES 加密和 PKCS #5 填充在 Java 中进行用户身份验证
【发布时间】:2014-11-07 11:54:08
【问题描述】:

我在 CBC 模式下使用 128 位 AES 加密和 PKCS #5 填充来将密码保存到我的数据库。 但是,当我尝试登录时,即使我使用了正确的密码,系统也会告诉我密码无效。

在我的 UserSetup 类中,这些是我用于加密密码并将其保存到我的数据库的代码:

try {
    String input = simple_text.getText();

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

    byte[] iv = new byte[cipher.getBlockSize()];
    new SecureRandom().nextBytes(iv);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);

    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(keyString.getBytes());
    byte[] key = new byte[16];
    System.arraycopy(digest.digest(), 0, key, 0, key.length);
    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");

    // encrypt
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
    byte[] encrypted = cipher.doFinal(input.getBytes("UTF-8"));
    System.out.println("encrypted: " + new String(encrypted));
    encrypt_text .setText(new String(encrypted));
} catch (Exception e2) {
    JOptionPane.showMessageDialog(null, e2);
}

try {
    String sql = "INSERT INTO user(username,password) VALUES(?,?) ON DUPLICATE KEY UPDATE username=VALUES(username),password=VALUES(password)";

    pst=conn.prepareStatement(sql);

    pst.setString(1, fLoginName.getText());
    pst.setString(2, encrypt_text.getText());

    pst.execute();

    JOptionPane.showMessageDialog(null, "saved");
} catch (Exception e2) {
    JOptionPane.showMessageDialog(null, e2);
}

在我的登录类中,我有以下代码:

 String sql ="select * from user where username=? and password=?";
 if(loginNameField.getText().equals("me") && passwordField.getText().equals("me")){
    frmLoginWindow.dispose();
    new GridMain().setVisible(true);                            
 }else{
    try{
        pst=conn.prepareStatement(sql);
        pst.setString(1,loginNameField.getText());
        pst.setString(2,passwordField.getText());

        rs=pst.executeQuery();

        if(rs.next()){
            //JOptionPane.showMessageDialog(null, "Username and Password is correct ");
            rs.close();
            pst.close();
            //  close();
            frmLoginWindow.dispose();
            new GridMain().setVisible(true);
        }
        else{
         JOptionPane.showMessageDialog(null, "Username and Password is not correct");
        }
    }
    catch(Exception e)
    {
           JOptionPane.showMessageDialog(null, e);
    } finally {
        try{
          rs.close();
          pst.close();
        }
        catch(Exception e) {}
    }
}

我的加密密码已成功保存,但我需要一种方法将我的登录密码与加密密码匹配,因为即使您加密相同的密码,AES 加密也不会给出相同的加密值。

【问题讨论】:

    标签: java security encryption


    【解决方案1】:

    AES 是一种加密算法。您尝试将其用作密码哈希算法。问题是多次加密同一事物不会每次都产生相同的结果。初始化向量 (IV) 在过程中引入了随机性,因此您不会两次得到相同的结果。

    您需要解密密码以检查它或切换到密码散列算法,例如 PBKDF2。请记住,AES 生成二进制数据 (byte[]),您不能简单地将其转换为 String。您需要使用 Base64 之类的东西对其进行编码。这对于散列函数的输出也可能是必需的。

    【讨论】:

    • 你是对的。我的问题是“我如何解密它?”对编码有帮助吗?
    • @myelow 与加密相同,不同之处在于您使用Cipher.DECRYPT_MODE而不是Cipher.ENCRYPT_MODE,并传递加密密码而不是明文密码。
    • 谢谢,但它给了我这个错误消息:“javax.crypto.IllegalBlockSizeException:使用填充密码解密时输入长度必须是 16 的倍数”
    • @myelow 这可能是因为您将密文从byte[] 转换为String,这样会丢失一些字符。在将密文保存到数据库之前,您需要将密文编码为 Base64,当您检索它时,将其从 Base64 转换回二进制。
    猜你喜欢
    • 2021-11-06
    • 2017-01-31
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    • 2019-08-17
    相关资源
    最近更新 更多