安全地 URL- 编码密码

Securely URL-encode a password

Java 为 URL 编码字符串提供 URLEncoder class。但是it is considered insecure to store passwords as Strings。此代码通过 POST 通过 HttpsURLConnection 输出流 wr 发送密码是否足够安全?

try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
    // Write some post params
    for (char c : pass) {
        wr.writeBytes(URLEncoder.encode(String.valueOf(c), "UTF-8"));
    }
    // Write some more
}

一方面是使用Strings。另一方面,这些字符串只有一个字符长,并且在编码后在概念上是相同的。此外,在我看来,这可能会在多字节字符上失败。攻击者能否在内存中找到这些 1 个字符的字符串并重建原始密码?有更好的方法吗?

一个OutputStream没有方法writeBytes;但它提供了一种 write(byte[]) 方法,可用于通过 one 调用来写入密码的 all 个字符。

除此之外:使用 HTTPS 的全部想法是连接本身是 安全加密;所以不管你是用单字节还是多字节突发传输这样的内容都无关紧要。

然后:请记住,所有这些 类 都是相互叠加的 抽象 。 HTTPS 使用 TCP; TCP数据包有一定的大小;从这个意义上说,无论如何都没有单个字节通过网络传输。

关于你问题的第二部分:你正在迭代一个 char 值数组。所以这真的取决于 如何 创建 char 数组;但通常情况下,您无需担心(请参阅有关该主题的 here)。

的确,当使用字符串作为密码时,您不能可靠地丢弃它们,因为您不能手动将 String 内容清零(除非通过反射)并且内容将保留在内存中一段时间未知时间。因此,通常建议将 char[] 用于任何密码输入,然后手动将所述 char[].

归零

然而,攻击绝非易事,因为它需要访问内存,运气好的话。密码不太可能在内存中保留很长时间,因为 GC 会执行其工作并且内存会被重用。在大多数情况下,与其他更简单的攻击相比,这种攻击向量是不可行的。