为了安全起见,将 new String(char[]) 作为密码参数传递给只接受字符串作为参数的方法是否安全?
For security, is it safe to pass new String(char[]) as an argument for passwords to a method that only accepts string as parameter?
我读过关于密码,使用 char[]
更理想,因为 Strings
是不可变的。
问题是,我需要将密码参数传递给调用 http 调用的第三方依赖项。它只接受字符串。该调用涉及在消息中发送密码,因此我使用方法:
new Request.Builder()
.url("notmyapi.com/login")
.method("POST", new FormBody.Builder()
.add("name", username)
.add("password", password)
.build())
.build()
我知道网络 api 只是按原样接受密码而不是接受 base64 版本或其他任何东西可能很糟糕,但这不是我的,我只需要做我的工作。
问题:
由于我现在将密码作为 char[]
传递,但是上面的 .add(key, value)
方法只接受一个字符串,所以 .add("password", new String(password))
安全吗?这会不会在内存中创建一个新的 String 实例,我应该出于安全考虑而试图避免这种情况?
I've read that for passwords, it's more ideal to use char[]
since Strings
are immutable.
这不是(全部)原因。实际推理是:
您正在使用密码以确保安全。
坏人可能能够获取 运行 JVM 的内存转储...或从保存(或保存)JVM 内存的磁盘块中提取部分转储页。该转储可能包含明文密码。
为了缓解这一问题,可以(应该)在不再需要密码时覆盖包含密码的内存。
很难覆盖 String
因为它是不可变的。
但是,如果您检查其中的每一点,就会发现一些假设可能会受到质疑。
密码不是实现安全性的好方法。对于高级安全性,您应该使用 public/private 密钥或密钥身份验证。因此,要么您是在谈论对您的系统来说 "less important" 的密码……要么您遇到的问题比您要在此处解决的问题更大。
如果坏人可以读取 JVM 内存或页面文件,那么他们已经深入到您的基础设施中了。你已经致命地妥协了。此外,如果他们陷得这么深,他们很可能会找到其他方法来窃取密码;例如窃取您的 SSL 证书私钥并窥探/解码加密的网络流量。
这只是一种缓解措施:
- 密码将在
char[]
一段时间内保持明文。
- 在密码到达您的代码之前,它们很可能已被 servlet 堆栈(或您使用的任何框架)转换为
String
对象。
- 此外,此缓解措施仅在您 覆盖代码中的
char[]
时才有效。
其实如果你真的很担心这个,可以使用反射来擦除一个String;即改变 String
对象。一般来说,这是一件危险的事情。对于密码/密码检查,这可能是可以接受的。
简而言之,我认为使用 char[]
而不是 String
在 Java 中实施太昂贵了....除非你准备好完全重新设计你的网络框架。此外,考虑到具有深度访问权限的人可以通过其他方式窃取密码,这样做的好处值得商榷。
现在回答您的具体问题:
Is it safe to do .add("password", new String(password))
如果您认为使用 String
作为密码存在风险,那么该代码就无济于事了。事实上,假设 password
是一个 String
,您现在在内存中有两个包含密码文本的 String
对象。
如果您使用的 API 要求您提供密码,因为 String
您有问题。
如果密码来源(即您如何从用户界面、servlet 框架等获取密码)是 String
,您就有问题了。
这两种情况都需要重新处理与您交互的代码的各个方面以解决问题。这可能很难。
并且:
I know it's probably bad that the web api is just accepting a password as it is instead of accepting a base64 version or whatever.
Base64 不会减慢坏人的速度超过一分钟左右。任何可逆编码均是如此。但我希望您坚持只能通过 SSL / TLS 安全连接发送密码。
无论您在客户端如何尝试,安全性都无关紧要,因为根据您在 post 中的代码,它似乎是一个简单的 http 客户端。所以它会基于http协议做一个简单的http请求。因此,您的密码将以纯文本形式出现在 http post 请求的正文中,例如 username=john&password=12345
恕我直言,你不需要从客户端做任何事情,如果网络 api 有一个启用了 ssl 的安全端点,那么你可以使用它
我读过关于密码,使用 char[]
更理想,因为 Strings
是不可变的。
问题是,我需要将密码参数传递给调用 http 调用的第三方依赖项。它只接受字符串。该调用涉及在消息中发送密码,因此我使用方法:
new Request.Builder()
.url("notmyapi.com/login")
.method("POST", new FormBody.Builder()
.add("name", username)
.add("password", password)
.build())
.build()
我知道网络 api 只是按原样接受密码而不是接受 base64 版本或其他任何东西可能很糟糕,但这不是我的,我只需要做我的工作。
问题:
由于我现在将密码作为 char[]
传递,但是上面的 .add(key, value)
方法只接受一个字符串,所以 .add("password", new String(password))
安全吗?这会不会在内存中创建一个新的 String 实例,我应该出于安全考虑而试图避免这种情况?
I've read that for passwords, it's more ideal to use
char[]
sinceStrings
are immutable.
这不是(全部)原因。实际推理是:
您正在使用密码以确保安全。
坏人可能能够获取 运行 JVM 的内存转储...或从保存(或保存)JVM 内存的磁盘块中提取部分转储页。该转储可能包含明文密码。
为了缓解这一问题,可以(应该)在不再需要密码时覆盖包含密码的内存。
很难覆盖
String
因为它是不可变的。
但是,如果您检查其中的每一点,就会发现一些假设可能会受到质疑。
密码不是实现安全性的好方法。对于高级安全性,您应该使用 public/private 密钥或密钥身份验证。因此,要么您是在谈论对您的系统来说 "less important" 的密码……要么您遇到的问题比您要在此处解决的问题更大。
如果坏人可以读取 JVM 内存或页面文件,那么他们已经深入到您的基础设施中了。你已经致命地妥协了。此外,如果他们陷得这么深,他们很可能会找到其他方法来窃取密码;例如窃取您的 SSL 证书私钥并窥探/解码加密的网络流量。
这只是一种缓解措施:
- 密码将在
char[]
一段时间内保持明文。 - 在密码到达您的代码之前,它们很可能已被 servlet 堆栈(或您使用的任何框架)转换为
String
对象。 - 此外,此缓解措施仅在您 覆盖代码中的
char[]
时才有效。
- 密码将在
其实如果你真的很担心这个,可以使用反射来擦除一个String;即改变
String
对象。一般来说,这是一件危险的事情。对于密码/密码检查,这可能是可以接受的。
简而言之,我认为使用 char[]
而不是 String
在 Java 中实施太昂贵了....除非你准备好完全重新设计你的网络框架。此外,考虑到具有深度访问权限的人可以通过其他方式窃取密码,这样做的好处值得商榷。
现在回答您的具体问题:
Is it safe to do
.add("password", new String(password))
如果您认为使用 String
作为密码存在风险,那么该代码就无济于事了。事实上,假设 password
是一个 String
,您现在在内存中有两个包含密码文本的 String
对象。
如果您使用的 API 要求您提供密码,因为
String
您有问题。如果密码来源(即您如何从用户界面、servlet 框架等获取密码)是
String
,您就有问题了。这两种情况都需要重新处理与您交互的代码的各个方面以解决问题。这可能很难。
并且:
I know it's probably bad that the web api is just accepting a password as it is instead of accepting a base64 version or whatever.
Base64 不会减慢坏人的速度超过一分钟左右。任何可逆编码均是如此。但我希望您坚持只能通过 SSL / TLS 安全连接发送密码。
无论您在客户端如何尝试,安全性都无关紧要,因为根据您在 post 中的代码,它似乎是一个简单的 http 客户端。所以它会基于http协议做一个简单的http请求。因此,您的密码将以纯文本形式出现在 http post 请求的正文中,例如 username=john&password=12345
恕我直言,你不需要从客户端做任何事情,如果网络 api 有一个启用了 ssl 的安全端点,那么你可以使用它