什么使字符串/令牌在密码学上是安全的?

What makes a string / token cryptographically secure?

如果您需要生成字符串/令牌来验证未来的请求(例如 API 密钥、电子邮件确认 URL 等),应考虑哪些因素?

特别

实例

让我们从 NodeJS 获取这两个输出字符串。

字符串 1(通过 Node crypto

var crypto = require('crypto');
crypto.randomBytes(48, function (ex, buf) {
  console.log(buf.toString('hex'));
});

字符串 2(通过 Node UUID

var uuid = require('node-uuid');
console.log(uuid.v4());

根据上述概念,哪一个更安全,为什么?

此外,请随时就该主题提出任何好的介绍 material,因为我在网上不容易找到关于此的文章。

What makes the string "secure" / "very hard to guess"?

字符串或令牌无法进行加密保护,因为它是 static

加密安全(伪)随机数生成器 (CS(P)RNG) 的概念描述了生成的数字是不可预测的。这是一个 属性 的过程,而不是个人的数字。

How is the "security amount" measured / estimated?

这取决于所使用的随机源,因为其中一些是黑匣子。你可以产生很多随机性,看看你是否能在其中找到一些模式。有 some test suites available,但是你必须考虑你的应用程序以及你需要多快的随机数。请求大量随机性可能会耗尽池,然后产生的随机数不足。

What are the main standards out there?

使用您的系统s/framework指定的加密安全随机源。 Node.js' crypto.randomBytes() 是其中之一,如果您想信任文档。

A practical example

node-uuid 使用 crypto.randomBytes() internally, so there is essentially the same randomness strength behind it, but it will fallback to Math.random() if crypto.randomBytes() is not available. Math.random() is not cryptographically secure. 如果你想在浏览器中有一个密码安全的随机值,你需要查询 Web Crypto API 的 getRandomValues().