简介
在一些使用情况下,一个程序可能需要一个安全的随机数生成源。通常情况下,我们需要随机数用于游戏功能,如骰子或抽奖,私钥生成,或其他类似的程序,需要一个加密的安全源。
在JavaScript中,我们有Math
对象中的random()
方法的本地实现,该对象是一个内置的对象,具有用于执行数学计算的属性或方法。random()
方法帮助我们生成随机数,顾名思义。
Math.random()
方法返回一个十进制数或浮点数,在零(包括)和一(不包括)之间的伪随机数。在数学术语中,这被表示为0 >= x < 1
。
虽然有不同的方法来使用这个方法在某些范围内产生随机结果,但Math.random()
并不是一个真正的随机数发生器。这是因为它是伪随机的;随着时间的推移,数字会开始重复,最终显示出非随机的模式。正如你可能知道的,计算机很难生成真正的随机数。
然而,虽然由Math.random()
生成的伪随机数通常在大多数情况下是足够的,但有时我们需要一个加密安全的随机数生成源。我的意思是,我们想要的随机数不能轻易通过模式来猜测,或者最终会随着时间的推移而重复。
在这篇文章中,我们将重点介绍这些情况下的推荐方法。但在此之前,让我们研究一下Math.random()
方法的一些基本用例,这样我们就可以学习在JavaScript中生成随机数的最简单方法。
Math.random()
方法在JavaScript中的使用情况
Math.random()
返回一个非加密的随机数,它从一个被称为 “种子 “的隐藏内部表示开始。种子代表了在指定范围内均匀生成的隐藏数字序列的起点。这个方法的一些用例解释如下。
Math.random()
方法的第一个(也是最简单的)用例是生成0到1之间的随机小数或浮点数字。
const randomNumber = Math.random()
console.log(randomNumber) outputs -> //0.8446144685704831
请注意,通过生成零到一之间的随机数,我们可以通过将随机数与另一个数字相乘,将结果扩大到我们需要的任何大小。
比如说。
const max = 6
const randomNumber = Math.floor(Math.random() * max)
console.log(randomNumber) outputs -> 0,1,2,3,4,5
这个方法的另一个用例是用Maths
对象中另一个名为floor
的方法生成两个特定整数范围之间的随机整数。floor
方法返回小于或等于指定数字的最大整数。
我们可以在一个指定的范围内生成一个浮点数,就像下面的例子。
// generating floating point numbers within a range
const max = 4
const min= 2
const result = Math.random()*(max - min)
console.log(result) //1.4597999233994834
// generating random integers within a range
const max = 4
const min= 2
const result = Math.random()*(max - min) + min
console.log(Math.floor(result))//3
Math.random()
函数的其他用例包括在某个指定范围内生成具有最大限制的随机数。在这里,我们可以利用ceil
,即Maths
对象中的另一个方法。
现在,在下一节中,让我们探讨一下利用这些伪随机数生成器的一些弊端。
中的安全隐患Math.random()
Math.random()
,在安全方面有几个缺点。根据MDN文档,Math.random()
并不能保证随机数的加密安全。因此,建议在我们的程序中不要用它们来做与安全有关的事情。
这些安全缺陷部分是由于以下原因。
- 在均匀分布范围内生成随机整数时采用的逻辑不充分,而且通常有偏见
- 浏览器在利用多少比特/字节的随机性方面的不一致
- 随机结果总是难以持续重放,使其具有非决定性和不规则性
- 内置的种子可以被篡改,使其在完整性方面不适合。
由于这些漏洞,万维网联盟提出了一个网络加密API的实现。在撰写本文时,所有流行的浏览器都通过crypto
对象为JavaScript应用程序提供了该API的实现。
让我们快速了解一下Web Crypto API以及如何使用它。
Web Crypto API简介
Web Crypto API提供了许多加密方法和函数,可以通过Window.crypto
属性访问。在浏览器中,我们可以利用crypto.getRandomValues(Int32Array)
,该方法承诺以加密方式生成随机数字。
在服务器端,Node.js也提供了一个标准Web Crypto API的实现。为了利用这个模块,我们可以用require('crypto').randomBytes(size)
来初始化它,因为加密包是Node的本机。
在Web Crypto API中使用的伪随机数生成器算法(PRNG)可能在不同的浏览器客户端中有所不同。然而,只要内部种子有足够的熵,它适用于大多数加密目的,可能来自外部来源,如Unix/dev/urandom
。
在下一节中,我们将讨论如何利用Web Crypto API,包括语法、我们可以传递的参数和返回值。让我们从下面的基本用法开始。
使用Web Crypto API
Crypto.getRandomValues()
方法让我们获得加密强度高的随机值。
从本质上讲,Crypto
接口代表了一种通用的加密功能。
它在大多数网络浏览器中都可以使用,虽然实现方式可能不同,但都需要使用一个具有足够熵的种子。这是为了确保不会对性能和安全产生负面影响。
getRandomValues()
方法是Crypto
接口的唯一成员,可以从不安全的环境中使用。因此,在生成加密密钥时不建议使用,因为它们不能保证返回安全的结果。在这种情况下,我们可以使用generateKey()
方法。
现在,让我们看看网页加密API的getRandomValues
方法的语法、接受的参数和返回值。
语法
网络密码学API接受ArrayBuffer
类和TypedArray
的实例作为输入,以表示字节序列。
请看下面的语法。
typedArray = cryptoObj.getRandomValues(typedArray);
参数
typedArray
是一个基于整数的TypedArray
对象。它可以是一个Int8Array
,一个Uint8Array
,一个Int16Array
,一个Uint16Array
,一个Int32Array
,或者一个Uint32Array
。
注意,数组中的所有元素都是用随机数填充的。
返回值
返回值是作为typedArray
传入的同一个数组,但其内容被新生成的随机数所取代。
在下一节中,我们将看看如何编写一个简单的程序来生成安全的加密随机数。
生成随机数
你为安全目的需要的每一个随机值(即任何存在攻击者可能性的地方),都应该使用加密安全伪随机数生成器,也被称为CSPRNG来生成。
这包括验证或重置令牌、抽奖号码、API密钥、生成的密码、加密密钥等等。
那么,我们如何才能生成安全、可靠的随机数呢?最好的选择是采用一个库,在设计上照顾到这些安全问题。在Node中,我们有几个选择。
- 对于生成范围内的随机数,有一个随机数-csprng,它使用引擎盖下的Crypto API。
- 对于API密钥或令牌**,**有uuid,特别是
uuid.v4()
函数。
让我们看看下面的一个例子。
旋转一个简单的Node应用程序,采用npm包中最简单的例子。
var Promise = require("bluebird");
var randomNumber = require("random-number-csprng");
Promise.try(function() {
return randomNumber(10, 30);
}).then(function(number) {
console.log("Your random number:", number);
}).catch({code: "RandomGenerationError"}, function(err) {
console.log("Something went wrong!");
});
Output shown below:
retina@alexander random-number-generator % node index.js
Your random number: 24
retina@alexander random-number-generator % node index.js
Your random number: 14
retina@alexander random-number-generator % node index.js
Your random number: 20
retina@alexander random-number-generator % node index.js
Your random number: 21
retina@alexander random-number-generator % node index.js
Your random number: 11
retina@alexander random-number-generator % node index.js
Your random number: 26
retina@alexander random-number-generator % node index.js
Your random number: 23
retina@alexander random-number-generator % node index.js
Your random number: 15
retina@alexander random-number-generator % node index.js
Your random number: 22
retina@alexander random-number-generator % node index.js
Your random number: 28
正如在上面的例子中看到的,我们可以在一个范围内生成加密安全的伪随机数。randomNumber
方法返回一个承诺,该承诺解析为指定范围内的一个随机数。更多细节可以在GitHub存储库的API部分找到。
在Node.js中使用Web Crypto API
Node.js提供了一个标准Web Crypto API的实现,尽管在撰写本文时,它仍然是该语言的一个实验性功能。
我们可以在Node中通过调用require('crypto').webcrypto
来使用这个模块。这将返回一个Crypto
类的实例,它提供了对加密API其余部分的访问。
正如我们前面所讨论的,
crypto.getRandomValues(typedArray)
生成密码学上的强随机值。关于Node中网络加密API的更多细节可以在Node文档中找到。
结论
真正的随机性,即没有模式或算法适用的随机性,是否真的存在是值得商榷的。然而,对于安全相关的代码,我们需要一个攻击者无法预测的随机数。在这种情况下,数据是如何产生的并不重要,只要它不能被猜到。
为此,万维网联盟发布了Web Cryptography API,它允许浏览器中的JavaScript应用程序使用常见的加密功能,而无需使用任何第三方库。
而正如我们前面提到的,这个API的crypto.getRandomValues
方法是网络应用程序获得加密安全的随机数据的最安全方式。
Web Crypto API的所有其他功能都可以通过crypto.subtle
对象访问。这里可以找到网络加密标准的链接。
感谢阅读 ,请不要犹豫,将你的问题或评论写在下面的部分。
The postBuilding a random number generator with JavaScript and Node.jsappeared first onLogRocket Blog.
今天的文章用JavaScript和Node.js构建一个随机数发生器分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/20522.html