我读过关于密码的信息,使用char []更理想,因为字符串是不可变的.
问题是,我需要将密码参数传递给调用http调用的第三方依赖项.它仅接受字符串.该调用涉及在消息中发送密码,因此我使用以下方法:
new Request.Builder()
.url("notmyapi.com/login")
.method("POST", new FormBody.Builder()
.add("name", username)
.add("password", password)
.build())
.build()
我知道Web 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内存页的磁盘块中提取部分转储.该转储可能包含明文密码.
>为了减轻这种情况,当不再需要密码时,可以(应该)覆盖包含密码的内存.
>由于字符串是不可变的,因此很难覆盖它.
但是,如果您检查所有这些点,则可能会质疑一些假设.
>密码不是实现安全性的好方法.为了获得较高的安全性,您应该使用公用/专用密钥或秘密密钥身份验证.因此,或者您谈论的是对系统“不太重要”的密码…或者您遇到的问题比您尝试在此处解决的问题更大.
>如果坏人可以读取JVM内存或页面文件,则它们已深入您的基础架构中.您已经受到致命伤害.此外,如果他们深入到此,他们很可能会找到其他方法来窃取密码.例如窃取您的SSL证书专用密钥并监听/解码加密的网络流量.
>这只是缓解措施:
>密码将在char []中以明文形式保留一段时间.
>在密码到达您的代码之前,它们很可能已被servlet堆栈(或您使用的任何框架)转换为String对象.
>此外,仅当您确实在代码中覆盖char []时,此缓解措施才有效.
>实际上,如果您真的对此感到担心,则可以使用反射来擦除字符串.即要对String对象进行突变.通常,这是一件危险的事情.对于密码/密码检查,这可能是可以接受的.
简而言之,我认为使用char []而不是String过于昂贵,无法在Java中实现….除非您准备好完全重新设计Web框架.此外,考虑到具有深度访问权限的人可以窃取密码的其他方式,这样做值得商benefit.
现在到您的特定问题:
Is it safe to do
.add("password", new String(password))
如果您认为使用字符串作为密码是有风险的,那么该代码将无济于事.实际上,假设密码是一个字符串,那么您现在在内存中有两个包含密码文本的String对象.
>如果您使用的API要求您以字符串形式提供密码,则有问题.
>如果密码的来源(即如何从用户界面,servlet框架等获取密码)是字符串,则表示问题.
>这两种情况都需要对与您交互的代码的各个方面进行重新处理以解决问题.这可能很困难.
和:
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安全连接发送.