3

我正在生成一个随机数来验证向导步骤以一个接一个地保护它。

我知道如何在 nodejs 中创建 nonce 并将其存储在数据库中以确保它可以使用一次。

但我想知道,是否有一个想法来生成和验证上面的随机数,比如只使用一次,如果可能的话,可以在时间限制(到期)内使用,而无需将其存储在数据库中,而只需将其返回到客户端在一个向导步骤中并在下一步中验证相同。

我通常使用下面的方法来生成随机数,对其进行规范化并将其存储在具有过期时间的 mongodb 中,以便 mongodb 将在特定时间后删除它,如果它没有被使用。

var crypto = require('crypto');

crypto.randomBytes(32, function (err, bytes) {
   if (err) {
       next(err);
    } else {
       next(null, normalize(bytes));
    }
});

请建议是否有任何好的/优化的方式来生成 nonce,以及在没有数据库调用的情况下处理一次性使用和到期的可能性。

4

3 回答 3

3

拥有一个数据库来存储和验证nonce. 要限制时间,您可以使用带有过期时间的 mongodb,也可以生成时间戳,然后生成hmac带有时间戳、随机数和私钥的时间戳。然后将 nonce、timestamp 和 hmac 发送给客户端。这样,如果您的数据库不支持文档到期作为 mongodb,您还可以保护时间戳以及限制特定时间的 nonce。希望它能解释。

于 2016-10-21T09:30:51.617 回答
1

可以在没有数据库调用的情况下使用过期的随机数,使用服务器上的哈希映射之类的东西来存储和检索随机数并检查时间。如果有会话 ID 或静态用户 ID,那会有所帮助。但是,与 MongoDB 等经过测试的解决方案相比,让服务器生成、保存、获取和维护 nonce 的想法似乎很困难。在服务的多个服务器的情况下会发生另一个问题,其中流量必须保持一致以使会话开始到结束。使用数据库作为随机数的单一事实来源可以解决这个问题。

如果在节点服务器上保留 nonce 的原因是为了速度/滞后,那么额外的测试和代码可能是值得的。在这种情况下,需要定期扫描 nonce 的超时以查找过期的,以保持快速搜索。

于 2016-10-25T06:46:29.567 回答
-3

编辑:此答案不能防止重放攻击,因此您需要数据库。

存储 nonce 的原因是为了确保它只能使用一次。这可以防止回复攻击,其中恶意方可能会拦截有效请求然后重新传输它。验证随机数的额外步骤可防止重播请求被接受。

为了防止某些类型的“重放”攻击,重要的是不仅要知道 nonce 是唯一的,而且要知道它没有在以前的请求中使用过。现实世界的例子:一家银行发行一张支票簿,其中每张支票都有一个唯一的号码。如果我给你写一张支票并签字,你就可以把它带到银行取钱。银行需要记录已兑现的每张支票的号码,否则您可以简单地复印我给您的原始支票并再次领取这笔钱

旧答案(我不删除它,因为它在数学上很优雅:)

如果您使用 128 位的加密随机数,则您有2^(128)数字的可能性。考虑到一个均匀分布的随机数生成器,并且您每秒调用一次这样的函数,重复的概率几乎为零。

您可以在节点中使用类似的东西(在此处转换为base64

const crypto = require('crypto');
var nonce = crypto.randomBytes(16).toString('base64');

128 位是 16 个字节。

数学演示

适用的二项分布的概率质量函数为

在此处输入图像描述

此函数返回在n次试验中恰好获得k次成功的概率,其中p是每次试验的成功概率。

在我们的例子p=1/(2^128)中。

累积函数为

在此处输入图像描述

其中k总和是k下的“地板”,即小于或等于k的最大整数。这个累积函数给出了成功次数在 0 和k之间的概率。

但是我们需要至少一次成功试验的概率,因为我们不想重复。考虑到这一点

在此处输入图像描述

因此

在此处输入图像描述

k=1意味着

在此处输入图像描述

在我们的例子中,如果我们在 100 年内每秒调用一次随机数,我们得到n=1*60*60*24*365.25*100=3155760000

所以

p=1/(2^128);
n=3155760000;

应用公式

在此处输入图像描述

结论

如果您使用 128 位 nonce,并且在 100 年内每秒调用一次 nonce,那么在 100 年内重复所说 nonce 的概率几乎为零,这意味着几乎不可能。这意味着您不需要数据库。

于 2018-04-29T16:13:02.000 回答