3

我们最近进行了一次安全审计,它暴露了这里现有系统中的几个弱点。由此产生的任务之一是我们需要更新我们的合作伙伴凭据系统,使其更加安全。

“旧”的做事方式是生成一个(错误的)密码,将其提供给具有 ID 的合作伙伴,然后他们将通过 https 发送该 ID 和该密码的 Base 64 编码副本以及他们的所有 XML 请求. 然后我们对它们进行解码并验证它们。

这些密码不会改变(因为我们的合作伙伴必须进行编码/配置更改才能更改它们,并且与数百个合作伙伴针对多个环境协调密码到期将是一场噩梦),并且它们不必由人类输入或人类可读的。如果我们的合作伙伴有更好但仍然相对简单的实施,我愿意改变这一点。

基本上它归结为两件事:我需要一个更安全的 Java 密码生成系统,并确保它们以安全的方式传输。

我发现了一些手动密码生成器,但没有什么能真正突出作为执行此操作的标准方法(也许有充分的理由)。可能还有一种比通过 https 进行简单 Base 64 编码更安全的方式来传输它们。

您会为密码生成器做什么,您认为现有的传输方法是否足够安全?

编辑:XML 来自 SOAP 消息,凭据位于标头中,而不是 XML 本身。此外,由于在设置密码时,每个合作伙伴的密码都是一次性操作,因此我们不太担心生成器的效率。

4

3 回答 3

6

密码生成

至于对传输密码进行编码,唯一真正增加安全性的编码是加密。使用 Base-64 或十六进制不是为了安全,而只是为了能够将其包含在 XML 等文本格式中。

熵用于衡量密码质量。因此,使用随机“硬币翻转”选择每一位将为您提供最优质的密码。您希望密码与其他加密密钥一样强大,因此我建议至少 128 位的熵。

有两种简单的方法,具体取决于您希望如何将密码编码为文本(从安全角度来看,这并不重要)。

对于Base-64,使用如下内容:

  SecureRandom rnd = new SecureRandom();
  /* Byte array length is multiple of LCM(log2(64), 8) / 8 = 3. */
  byte[] password = new byte[18];
  rnd.nextBytes(password);
  String encoded = Base64.encode(password);

以下内容不需要您提供 Base-64 编码器。生成的编码不是那么紧凑(26 个字符而不是 24 个),并且密码没有那么多的熵。(但 130 位已经很多了,与人类选择的至少 30 个字符的密码相当。)

SecureRandom rnd = new SecureRandom();
/* Bit length is multiple of log2(32) = 5. */
String encoded = new BigInteger(130, rnd).toString(32); 

创建新的 SecureRandom 对象的计算成本很高,因此如果您要频繁生成密码,您可能需要创建一个实例并保留它。

更好的方法

将密码嵌入 XML 本身似乎是一个错误。

首先,您似乎希望在处理他们发送给您的任何文件之前对发件人进行身份验证。假设我讨厌你的胆量,并开始向你发送巨大的 XML 文件来执行拒绝服务攻击。您是否只想解析 XML 以发现我不是合法合作伙伴?如果 servlet 只是预先拒绝来自未经身份验证的用户的请求,不是更好吗?

其次,您的合法合作伙伴的密码在传输过程中受到 HTTPS 的保护,但现在它们很可能以“明文形式”存储在您系统的某个地方。那安全性很差。

更好的方法是在合作伙伴向您发送包含 HTTP 请求标头中的凭据的文档时对其进行身份验证。如果您只允许 HTTPS,则可以将密码完全从文档中取出,并将其放入HTTP“基本”身份验证标头中。它在传输过程中受到 SSL 的保护,并且不会以明文形式存储在您的系统中(您仅存储单向哈希以用于身份验证)。

HTTP 基本身份验证简单、受广泛支持,并且比 SSL 客户端证书更容易为您和您的合作伙伴实施。

保护文档内容

如果文档本身的内容是敏感的,那么它们确实应该由发件人加密,并由您以加密形式存储。最好的方法是使用公钥加密,但这将是另一个问题的主题。

于 2008-09-19T17:11:02.067 回答
0

我不清楚为什么您的审计团队认为通过 SSL(通过 HTTPS)传输密码是“不安全的”。因此,当您要求两件事时,似乎第二件事——确保密码以安全的方式传输——已经得到很好的处理。

至于第一个,我们必须知道审计将您的密码暴露为不安全的情况......

于 2008-09-19T16:51:54.267 回答
0

我会放弃整个密码方法并开始使用允许 2 端经过身份验证的 SSL 连接的客户端证书。

您必须为每个客户端生成并签署单独的证书。在 SSL 握手中,您请求客户端的证书并对其进行验证。如果失败,则连接以 401 状态码结束。

您可以随时撤销证书,从而轻松断开以前的客户。

由于所有这些都发生在通信之前的握手中,因此不可能用数据淹没您的服务器。

于 2008-09-24T15:24:23.983 回答