当前位置: 首页 > 知识库问答 >
问题:

在Java中,使用char[]代替String来存储密码还有意义吗?

蔺劲
2023-03-14

我了解到使用char[]在comp.lang.java.*的Usenet天存储密码。

搜索StackOverflow也可以很容易地找到这样的高投票率问题:为什么char[]比String更适合密码?这与我很久很久以前学到的是一致的。

我仍然编写我的API以使用字符[]作为密码。但现在,这仅仅是空洞的理想吗?

例如,看看Atlassian Jira的Java API:LoginManager。authenticate,它将您的密码作为字符串。

或者是泰雷兹的Luna Java API:all people的LunaSlotManager中的login()方法,这是一家HSM厂商,使用字符串作为HSM槽密码。

我想我还在某个地方读到过URLConnection的内部结构(以及许多其他类)在内部使用字符串来处理数据。因此,如果您发送密码(尽管密码是由TLS通过网络加密的),它将在服务器内存中的字符串中。

访问服务器内存是一个很难实现的攻击因素吗?现在可以将密码存储为String了吗?或者,由于其他人编写的类,您的密码将以String结尾,这就是泰雷兹这样做的原因。

共有2个答案

夹谷成龙
2023-03-14

这不是通过网络传输的时刻的想法。确实,您确实最好使用String,因为它只是更方便地用于通过网络发送,当然要确保它已正确加密。

对于在应用程序中使用密码,由于堆栈转储和逆向工程以及字符串不可变的问题而有所不同:如果输入了密码,即使对变量的引用被更改为另一个字符串,也不确定垃圾收集器何时会真正从堆中删除字符串。因此,能够看到转储的黑客也将能够看到密码。使用char数组可以防止这种情况,因为您可以直接更改数组中的数据,而无需依赖垃圾收集器。

现在你可能会说:那么当它以字符串形式通过网络发送时,它仍然是可见的,不是吗?是的,但这就是为什么在发送之前加密它很重要。尽可能不要通过网络发送纯文本密码。

东方河
2023-03-14

首先,让我们回顾一下推荐使用char[]而不是String的原因:Strings是不可变的,因此一旦创建了字符串,对字符串内容的控制就会受到限制,直到(可能是在)内存被垃圾收集。可以转储进程内存的攻击者因此可以潜在地读取密码数据。同时,char[]对象的内容可以在创建后被覆盖。假设GC在此期间没有将对象移动到另一个物理内存位置,这意味着密码内容可以在使用后被(某种程度上)确定性地销毁。在该点之后读取进程内存的攻击者将无法获取密码。

因此,使用char[]而不是String可以防止非常特定的攻击场景:攻击者可以完全访问进程内存,但仅限于特定的时间点,而不是持续的。即使在这种场景下,使用char[]也不能阻止攻击,它只是降低了攻击成功的机会(如果攻击者碰巧在创建和擦除密码之间读取了进程内存,他们可以读取它)。

我不知道有任何证据表明(a)这种情况有多频繁,也不知道(b)使用char[]在多大程度上改变了这种情况下的成功概率。据我所知,这纯粹是猜测。

事实上,在大多数系统上,这种情况可能根本不存在:可以访问其他进程内存的攻击者也可以获得完全跟踪访问权。例如,在Linux和Windows上,任何可以读取另一个进程内存的进程也可以向该进程注入任意逻辑(例如,通过LD_PRELOAD和类似机制1)。所以我想说,使用char[]最多只能带来有限的好处,而且可能根本没有好处。

…事实上,我可以想到一个具体的反例:加载不受信任的插件库的应用程序。一旦通过传统方式(即在同一内存空间中)加载该库,它就可以访问父应用程序。在这种情况下,如果在加载插件之前处理密码,则使用char[]而不是String可能是有意义的。但是更好的解决方案是不要将不受信任的插件加载到同一内存空间中。一个常见的替代方案是在单独的进程中启动它并通过IPC进行通信。

1虽然LD_PRELOAD特别要求攻击者不仅可以访问另一个进程,还可以启动该进程或访问其父进程。

 类似资料:
  • 我试图建立一个替代密码。对于我的密钥,我使用一个随机的256字节数组,它是256个可能字节值的排列。 这是通过以下方式设置的: 然后,我用以下方法对消息进行编码/解码: 在这个过程中,有些东西出了问题,我解码的任何东西都会作为一个 我不确定自己哪里出错了,也不确定这是否是最高效的做事方式,我必须保持相同的函数签名和通用方法,但实现细节由我决定。 感谢任何和所有的帮助。

  • 我正在尝试为一个网站构建一个非官方的api。它将要求用户登录,密码将使用标准的Console.readPassword()方法从控制台读取。现在,这给了我一个char数组,但是我必须使用Apache的HttpClient库中的HttpPost类通过POST请求发送密码。为此,需要一个字符串,但是将密码转换为字符串会产生安全风险。我能做什么? 编辑:我知道如何将字符数组转换为字符串。问题是Strin

  • 问题内容: 我曾经生成过RSA密钥对。如果我没看错,那么KeyStore仅用于存储证书,而不用于存储密钥。如何将私钥正确存储在计算机上? 问题答案: 注意:此代码仅用于演示目的。将私钥存储在磁盘上时,必须对其进行加密。不要按原样使用它。 您可以执行以下操作: 保存功能: 并以相同的方式读回: 读取私钥相似。

  • 我正在学习JAVA OCA认证书。我在二元运算符一章。这本书提到了以下规则。 、和在使用二进制运算符时将提升为int。 因此,目前,如果我定义并初始化一个short或byte类型的变量,它将自动转换为int。在书中,它说赋值是一个二进制运算符。 使用这些变量有什么意义吗? 如何在java中打印这种类型的变量?

  • 问题内容: 我正在用Java编写一个针对Mac OS X的小程序(Twitter客户端)。作为其功能的一部分,它需要有一个存储Twitter用户名/密码的地方。自然的地方是Mac钥匙串,但我找不到任何访问它的方法。 有什么方法可以从Java访问mac钥匙串,或者失败了,对于在哪里存储用户名/密码,您有何建议? 问题答案: 有Java钥匙串API,在OS X上有一个由keychain支持的KeySt

  • 问题内容: 我正在尝试调用本机语言。到目前为止,这是我所拥有的(它会出现总线错误): 它确实正确调用了函数,并且到达了ret指令。但是,当它尝试执行ret指令时,会出现SIGBUS错误。是因为我在未清除执行页面之类的代码上执行代码吗? 那我在做什么错呢? 问题答案: 第一个问题可能是该编数据的存储位置不可执行。 至少在Linux上,生成的二进制文件会将全局变量的内容放在“数据”段或此处,这在大多数