简体   繁体   English

安全地对密码进行URL编码

[英]Securely URL-encode a password

Java provides the URLEncoder class for URL-encoding Strings. Java为URL编码字符串提供URLEncoder类。 But it is considered insecure to store passwords as Strings . 但是将密码存储为String被认为是不安全的 Is this code to send a password via POST over an HttpsURLConnection output stream wr secure enough? 此代码通过HttpsURLConnection输出流wr通过POST发送密码是否足够安全?

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
}

On the one hand, it is using Strings. 一方面,它使用字符串。 On the other hand, those Strings are 1 character long, and conceptually the same after encoding. 另一方面,这些字符串的长度为1个字符,并且在编码后在概念上相同。 Also, it seems to me that this could fail on multi-byte characters. 另外,在我看来,这可能在多字节字符上失败。 Would an attacker be able to locate these 1-char Strings in memory and reconstruct the original password? 攻击者能否在内存中找到这些1个字符的字符串并重建原始密码? Is there a better way to do this? 有一个更好的方法吗?

It's true that when using Strings for passwords, you can't reliably discard them since you can't zero out the String contents manually (except through reflection) and the contents will stay in memory for an unknown time. 的确,当使用字符串作为密码时,您不能可靠地丢弃它们,因为您不能手动将String内容归零(通过反射除外),并且该内容将在内存中保留未知的时间。 Therefore char[] is often recommended to be used for any password input, followed by a manual zeroing of the said char[] . 因此,通常建议将char[]用于任何密码输入,然后手动将所述char[]归零。

However the attack is in no way easy to mount since it requires access to the memory, luck with timing. 但是,这种攻击绝非易事,因为它需要访问内存,运气不错。 It's unlikely the password will stay in the memory for very long amounts of time, as the GC does its work and the memory gets reused. 密码不太可能在内存中保留很长时间,因为GC会工作并且内存会被重用。 In most cases this attack vector can be infeasible compared to other, simpler attacks. 在大多数情况下,与其他更简单的攻击相比,这种攻击媒介是不可行的。

An OutputStream has no method writeBytes ; 一个OutputStream没有方法writeBytes ; but it offers a write(byte[]) method that could be used to write all chars of the password with one call. 但它提供了write(byte [])方法,可用于一次调用写入密码的所有字符。

And beyond that: the whole idea of using HTTPS is that the connection itself is securely encrypted ; 除此之外:使用HTTPS的整个想法是对连接本身进行安全加密 so it really should not matter whether you transmit such content with single byte or multi byte bursts. 因此,以单字节突发还是多字节突发传输此类内容真的不重要。

Then: keep in mind that all these classes are abstractions , that are layered upon each other. 然后:请记住,所有这些类都是抽象 ,彼此抽象 HTTPS uses TCP; HTTPS使用TCP; and TCP packets have a certain size; TCP报文有一定的大小; in that sense there aren't single bytes going over the network anyway. 从这种意义上讲,网络上没有单个字节通过。

And regarding the second part of your question: you are iterating an array of char values. 关于问题的第二部分:您正在迭代一个char值数组。 So it really depends how that char array was created; 因此,它实际上取决于该字符数组是如何创建的; but normally, you don't need to worry (see here on that topic). 但通常,您不必担心(请参阅此处的该主题)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM