您将如何在Java中实现安全的静态登录凭据系统?

时间:2022-12-09 10:05:50

We recently had a security audit and it exposed several weaknesses in the systems that are in place here. One of the tasks that resulted from it is that we need to update our partner credentials system make it more secure.

我们最近进行了一次安全审计,它暴露了这里的系统存在的一些弱点。由此产生的任务之一是我们需要更新我们的合作伙伴凭证系统,以使其更安全。

The "old" way of doing things was to generate a (bad) password, give it to the partner with an ID and then they would send that ID and a Base 64 encoded copy of that password in with all of their XML requests over https. We then decode them and validate them.

“旧的”处理方式是生成(坏)密码,将其提供给具有ID的伙伴,然后他们将通过https发送该ID和该密码的Base 64编码副本以及所有XML请求。然后我们解码它们并验证它们。

These passwords won't change (because then our partners would have to make coding/config changes to change them and coordinating password expirations with hundreds of partners for multiple environments would be a nightmare) and they don't have to be entered by a human or human readable. I am open to changing this if there is a better but still relatively simple implementation for our partners.

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

Basically it comes down to two things: I need a more secure Java password generation system and to ensure that they are transmitted in a secure way.

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

I've found a few hand-rolled password generators but nothing that really stood out as a standard way to do this (maybe for good reason). There may also be a more secure way to transmit them than simple Base 64 encoding over https.

我找到了一些手动密码生成器,但没有什么真正脱颖而出作为标准的方法来做到这一点(也许是有充分理由的)。传输它们可能比通过https进行简单的Base 64编码更安全。

What would you do for the password generator and do you think that the transmission method in place is secure enough for it?

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

Edit: The XML comes in a SOAP message and the credentials are in the header not in the XML itself. Also, since the passwords are a one-off operation for each partner when we set them up we're not too worried about efficiency of the generator.

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

4 个解决方案

#1


6  

Password Generation

As far as encoding a password for transmission, the only encoding that will truly add security is encryption. Using Base-64 or hexadecimal isn't for security, but just to be able to include it in a text format like XML.

就编码密码进行传输而言,唯一真正增加安全性的编码就是加密。使用Base-64或十六进制不是为了安全,而是为了能够以XML等文本格式包含它。

Entropy is used to measure password quality. So, choosing each bit with a random "coin-flip" will give you the best quality password. You'd want passwords to be as strong as other cryptographic keys, so I'd recommend a minimum of 128 bits of entropy.

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

There are two easy methods, depending on how you want to encode the password as text (which really doesn't matter from a security standpoint).

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

For Base-64, use something like this:

对于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);

The following doesn't require you to come up with a Base-64 encoder. The resulting encoding is not as compact (26 characters instead of 24) and the password doesn't have as much entropy. (But 130 bits is already a lot, comparable to a password of at least 30 characters chosen by a human.)

以下内容不要求您提供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); 

Creating new SecureRandom objects is computationally expensive, so if you are going to generate passwords frequently, you may want to create one instance and keep it around.

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

A Better Approach

Embedding the password in the XML itself seems like a mistake.

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

First of all, it seems like you would want to authenticate a sender before processing any documents they send you. Suppose I hate your guts, and start sending you giant XML files to execute a denial of service attack. Do you want to have to parse the XML only to find out that I'm not a legitimate partner? Wouldn't it be better if the servlet just rejected requests from unauthenticated users up front?

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

Second, the passwords of your legitimate partners were protected during transmission by HTTPS, but now they are likely stored "in the clear" on your system somewhere. That's bad security.

其次,您的合法合作伙伴的密码在通过HTTPS传输时受到保护,但现在它们很可能存储在您系统的“明确”位置。那是不好的安全。

A better approach would be to authenticate partners when they send you a document with credentials in the HTTP request headers. If you only allow HTTPS, you can take the password out of the document completely and put it into an HTTP "Basic" authentication header instead. It's secured by SSL during transmission, and not stored on your system in the clear (you only store a one-way hash for authentication purposes).

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

HTTP Basic authentication is simple, widely supported, and will be much easier for you and your partners to implement than SSL client certificates.

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

Protecting Document Content

If the content of the documents themselves is sensitive, they really should be encrypted by the sender, and stored by you in their encrypted form. The best way to do this is with public key cryptography, but that would be a subject for another question.

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

#2


1  

Couldn't you use SSL Keys for authentication?

你不能使用SSL密钥进行身份验证吗?

#3


0  

I'm unclear why transmitting the passwords over SSL -- via HTTPS -- is being considered "insecure" by your audit team. So when you ask for two things, it seems the second -- ensuring that the passwords are being transmitted in a secure way -- is already being handled just fine.

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

As for the first, we'd have to know what about the audit exposed your passwords as insecure...

至于第一个,我们必须知道审计暴露你的密码是不安全的...

#4


0  

I'd abandon the whole password approach and start using client certificates allowing a 2 side authenticated SSL connection.

我放弃了整个密码方法并开始使用客户端证书,允许双方认证的SSL连接。

You have to generate and sign individual certificates for each client. In the SSL handshake, you request the client's certificate and verify it. If it fails, the connection ends with a 401 status code.

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

Certificates can be revoked at any time be your side, allowing easily disconnecting former customers.

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

Since all this happens in the handshake prior to the communication, is is not possible to flood your server with data.

由于所有这些都发生在通信之前的握手中,因此无法使服务器充满数据。

#1


6  

Password Generation

As far as encoding a password for transmission, the only encoding that will truly add security is encryption. Using Base-64 or hexadecimal isn't for security, but just to be able to include it in a text format like XML.

就编码密码进行传输而言,唯一真正增加安全性的编码就是加密。使用Base-64或十六进制不是为了安全,而是为了能够以XML等文本格式包含它。

Entropy is used to measure password quality. So, choosing each bit with a random "coin-flip" will give you the best quality password. You'd want passwords to be as strong as other cryptographic keys, so I'd recommend a minimum of 128 bits of entropy.

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

There are two easy methods, depending on how you want to encode the password as text (which really doesn't matter from a security standpoint).

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

For Base-64, use something like this:

对于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);

The following doesn't require you to come up with a Base-64 encoder. The resulting encoding is not as compact (26 characters instead of 24) and the password doesn't have as much entropy. (But 130 bits is already a lot, comparable to a password of at least 30 characters chosen by a human.)

以下内容不要求您提供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); 

Creating new SecureRandom objects is computationally expensive, so if you are going to generate passwords frequently, you may want to create one instance and keep it around.

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

A Better Approach

Embedding the password in the XML itself seems like a mistake.

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

First of all, it seems like you would want to authenticate a sender before processing any documents they send you. Suppose I hate your guts, and start sending you giant XML files to execute a denial of service attack. Do you want to have to parse the XML only to find out that I'm not a legitimate partner? Wouldn't it be better if the servlet just rejected requests from unauthenticated users up front?

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

Second, the passwords of your legitimate partners were protected during transmission by HTTPS, but now they are likely stored "in the clear" on your system somewhere. That's bad security.

其次,您的合法合作伙伴的密码在通过HTTPS传输时受到保护,但现在它们很可能存储在您系统的“明确”位置。那是不好的安全。

A better approach would be to authenticate partners when they send you a document with credentials in the HTTP request headers. If you only allow HTTPS, you can take the password out of the document completely and put it into an HTTP "Basic" authentication header instead. It's secured by SSL during transmission, and not stored on your system in the clear (you only store a one-way hash for authentication purposes).

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

HTTP Basic authentication is simple, widely supported, and will be much easier for you and your partners to implement than SSL client certificates.

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

Protecting Document Content

If the content of the documents themselves is sensitive, they really should be encrypted by the sender, and stored by you in their encrypted form. The best way to do this is with public key cryptography, but that would be a subject for another question.

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

#2


1  

Couldn't you use SSL Keys for authentication?

你不能使用SSL密钥进行身份验证吗?

#3


0  

I'm unclear why transmitting the passwords over SSL -- via HTTPS -- is being considered "insecure" by your audit team. So when you ask for two things, it seems the second -- ensuring that the passwords are being transmitted in a secure way -- is already being handled just fine.

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

As for the first, we'd have to know what about the audit exposed your passwords as insecure...

至于第一个,我们必须知道审计暴露你的密码是不安全的...

#4


0  

I'd abandon the whole password approach and start using client certificates allowing a 2 side authenticated SSL connection.

我放弃了整个密码方法并开始使用客户端证书,允许双方认证的SSL连接。

You have to generate and sign individual certificates for each client. In the SSL handshake, you request the client's certificate and verify it. If it fails, the connection ends with a 401 status code.

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

Certificates can be revoked at any time be your side, allowing easily disconnecting former customers.

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

Since all this happens in the handshake prior to the communication, is is not possible to flood your server with data.

由于所有这些都发生在通信之前的握手中,因此无法使服务器充满数据。