【问题标题】:How to get String from byte array which is generated PBKDF2 password如何从生成 PBKDF2 密码的字节数组中获取字符串
【发布时间】:2018-09-10 09:16:30
【问题描述】:

我使用here的解决方案:

public static byte[] getEncryptedPassword(String password, byte[] salt,  int iterations,  int derivedKeyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
    KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength * 8);
    SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
    return f.generateSecret(spec).getEncoded();
}

问题是当我这样做时:

System.out.println(new String(getEncryptedPassword(p,s,i,l)));

我得到一个非常奇怪的字符串,例如���:,但我想要一个可以保存在数据库中的普通字符串。我的错误是什么?

【问题讨论】:

    标签: java security pbkdf2


    【解决方案1】:

    如果您想将byte[] 之类的二进制数据转换为字符串,您通常会将其编码为 Hex 或 Base64 格式。 Base64 比 hex 小,所以我建议你使用这个。

    对于 Base64,您可以从 Java 8 开始使用 java.util.Base64

    String base64encoded = Base64.getEncoder().encodeToString(getEncryptedPassword(p,s,i,l)));

    对于Hex AFAIR Java 不包含必要的代码。您可以使用例如Hex encode 来自Apache common codec

    String hexEncoded = Hex.encodeHexString(getEncryptedPassword(p,s,i,l)));

    【讨论】:

    • 感谢您的回答。我使用你写的 Base64 并得到了正常的字符串。唯一的问题是我将长度(l)传递为128,但得到长度为172的base64编码字符串。如何解释?
    • Base64 编码的消息总是更长,因为字符串中只能使用可打印的字符(因此您浪费了一些位)。使用十六进制编码,长度甚至更长:它是输入长度的两倍。如果您想将数据保持在最低限度,请不要对其进行编码并将byte[] 保存为您的数据库中的BLOBVARBINARY(如果其中一种类型支持作为列类型)。
    • 你能说 - 我的错误是 PBEKeySpec 需要(二进制)字节而不是字符串,并且还返回字节而不是字符串。但我试图用这些字节中的字符制作normal String。我说的对吗?
    • PBEKeySpec 的输入完全不相关。它总是输出一个字节[],这正是它的设计目的。是的,您尝试将二进制数据的字节 [] 直接解释为字符串。这永远不会适用于真正的二进制数据。
    • 非常感谢您的详细解释。对于十六进制编码,我发现 docs.oracle.com/javase/9/docs/api/javax/xml/bind/… 见 printHexBinary。
    猜你喜欢
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 2022-11-19
    • 2011-05-31
    • 1970-01-01
    相关资源
    最近更新 更多