java UUID.randomUUID() 是否适合用作一次性密码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11026061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 03:29:07  来源:igfitidea点击:

Is UUID.randomUUID() suitable for use as a one-time password?

javarandomsecurityuuid

提问by cqcallaw

As previous discussed, confirmation emails should have a unique, (practically) un-guessable code--essentially a one-time password--in the confirmation link.

正如前面所讨论的,确认电子邮件应该有一个独特的,(几乎)未猜测的代码-基本上是一个一次性密码--in确认链接。

The UUID.randomUUID() docssay:

UUID.randomUUID() 文档说:

The UUID is generated using a cryptographically strong pseudo random number generator.

UUID 是使用加密强的伪随机数生成器生成的。

Does this imply that the the UUID random generator in a properly implemented JVM is suitable for use as the unique, (practically) un-guessable OTP?

这是否意味着正确实现的 JVM 中的 UUID 随机生成器适合用作唯一的、(实际上)不可猜测的 OTP?

采纳答案by jchook

No.According to the UUID spec:

不。根据UUID 规范

Do not assume that UUIDs are hard to guess; they should not be used as security capabilities (identifiers whose mere possession grants access), for example. A predictable random number source will exacerbate the situation.

不要假设 UUID 很难猜测;例如,它们不应该用作安全功能(仅拥有就可以访问的标识符)。可预测的随机数源会加剧这种情况。

Also, UUIDs only have 16 possible characters (0 through F). You can generate a much more compact and explicitly secure random password using SecureRandom(thanks to @erickson).

此外,UUID 只有 16 个可能的字符(0 到 F)。您可以使用SecureRandom(感谢@erickson)生成更紧凑且明确安全的随机密码。

import java.security.SecureRandom;
import java.math.BigInteger;

public final class PasswordGenerator {
    private SecureRandom random = new SecureRandom();

    public String nextPassword() {
        return new BigInteger(130, random).toString(32);
    }
}

回答by andrew cooke

if you read the RFCthat defines UUIDs, and which is linked to from the API docs, you'll see that not all bits of the UUID are actually random (the "variant" and the "version" are not random). so a type 4 UUID (the kind that you intend to use), if implemented correctly, should have 122 bits of (secure, for this implementation) random information, out of a total size of 128 bits.

如果您阅读定义 UUID 并从 API 文档链接到的RFC,您会发现并非 UUID 的所有位实际上都是随机的(“变体”和“版本”不是随机的)。因此,如果正确实施,类型 4 UUID(您打算使用的那种)应该具有 122 位(安全,对于此实施)随机信息,总大小为 128 位。

so yes, it will work as well as a 122 bit random number from a "secure" generator. buta shorter value may contain a sufficient amount of randomness and might be easier for a user (maybe i am the only old-fashioned person who still reads email in a terminal, but confirmation URLs that wrap across lines are annoying....).

所以是的,它可以像来自“安全”生成器的 122 位随机数一样工作。 但是较短的值可能包含足够的随机性,并且对用户来说可能更容易(也许我是唯一一个仍在终端中阅读电子邮件的老式人,但是跨行的确认 URL 很烦人......) .

回答by Alex Lockwood

Yes, using a java.util.UUIDis fine, randomUUIDmethods generates from a cryptographically securesource. There's not much more that needs to be said.

是的,使用 ajava.util.UUID很好,randomUUID方法从加密安全源生成。没有更多需要说的了。

Here's my suggestion:

这是我的建议:

  1. Send the user a link with a huge password in it as the URL argument.
  2. When user clicks the link, write your backend so that it will determine whether or not the argument is correct and that the user is logged in.
  3. Invalidate the UUID 24 hours after it has been issued.
  1. 向用户发送一个包含巨大密码的链接作为 URL 参数。
  2. 当用户单击链接时,编写您的后端,以便它确定参数是否正确以及用户是否已登录。
  3. 在 UUID 发出 24 小时后使其失效。

This will take some work, but it's necessary if you really care about writing a robust, secure system.

这将需要一些工作,但如果您真的关心编写一个健壮、安全的系统,这是必要的。

回答by Dai

If it's generated by a CSRNG then it's unpredictable and so can be used.

如果它是由 CSRNG 生成的,那么它是不可预测的,因此可以使用。

But the trouble you're going to is wasted if you're sending out confirmation emails unencrypted - if an attacker has the means of predicting RNG results from your system then chances are they can intercept emails too.

但是,如果您发送未加密的确认电子邮件,那么您将要遇到的麻烦就是浪费——如果攻击者有办法从您的系统中预测 RNG 结果,那么他们很可能也可以拦截电子邮件。

UUIDs are also long strings (128-bits then typically Base64 (22 chars) or Base16-encoded (32 chars)) - think about how user-friendly your system will be. Personally I'd use a CSRNG to select 8 alphanumeric characters at random and return those.

UUID 也是长字符串(128 位,然后通常为 Base64(22 个字符)或 Base16 编码(32 个字符))- 考虑一下您的系统对用户的友好程度。我个人会使用 CSRNG 随机选择 8 个字母数字字符并返回这些字符。

回答by Fang-Pen Lin

The point of the random code for a confirmation link is that the attacker should not be able to guess nor predict the value. As you can see, to find the correct code to your confirmation link, a 128bits length UUID yields 2^128 different possible codes, namely, 340,282,366,920,938,463,463,374,607,431,768,211,456 possible codes to try. I think your confirmation link is not for launching a nuclear weapon, right? This is difficult enough for attacker to guess. It's secure.

确认链接的随机代码的意义在于攻击者不应该能够猜测或预测该值。如您所见,要找到确认链接的正确代码,128 位长度的 UUID 会产生 2^128 个不同的可能代码,即 340,282,366,920,938,463,463,374,607,431,768,211,456 种可能的代码供尝试。我认为您的确认链接不是用于发射核武器,对吗?这对于攻击者来说是很难猜到的。这是安全的。

-- update --

- 更新 -

If you don't trust the cryptographically strongrandom number generator provided, you can put some more unpredictable parameters with the UUID code and hash them. For example,

如果您不信任提供的加密强随机数生成器,您可以在 UUID 代码中放置一些更不可预测的参数并对其进行哈希处理。例如,

code = SHA1(UUID, Process PID, Thread ID, Local connection port number, CPU temperature)

code = SHA1(UUID、进程PID、线程ID、本地连接端口号、CPU温度)

This make it even harder to predict.

这使得预测变得更加困难。

回答by wattostudios

I think this should be suitable, as it is generated randomly rather than from any specific input (ie you're not feeding it with a username or something like that) - so multiple calls to this code will give different results. It states that its a 128-bit key, so its long enough to be impractical to break.

我认为这应该是合适的,因为它是随机生成的,而不是来自任何特定输入(即您没有使用用户名或类似的东西来提供它)-因此多次调用此代码会产生不同的结果。它声明它是一个 128 位的密钥,所以它足够长,无法破解。

Are you then going to use this key to encrypt a value, or are you expecting to use this as the actual password? Regardless, you'll need to re-interpret the key into a format that can be entered by a keyboard. For example, do a Base64 or Hex conversion, or somehow map the values to alpha-numerics, otherwise the user will be trying to enter byte values that don't exist on the keyboard.

然后您打算使用此密钥来加密一个值,还是希望将其用作实际密码?无论如何,您需要将密钥重新解释为可以通过键盘输入的格式。例如,进行 Base64 或 Hex 转换,或以某种方式将值映射到字母数字,否则用户将尝试输入键盘上不存在的字节值。

回答by Anuj Balan

It is perfect as one time password, as even I had implemented the same for application on which am working. Moreover, the link which you've shared says it all.

它是完美的一次性密码,因为即使我已经为正在运行的应用程序实现了相同的密码。此外,您分享的链接说明了一切。

回答by Mercury

I think java.util.UUID should be fine. You can find more information from this article:

我认为 java.util.UUID 应该没问题。您可以从这篇文章中找到更多信息: