Javascript 在javascript中保护随机数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4083204/
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
Secure random numbers in javascript?
提问by Kyle
How do I generate cryptographically secure random numbers in javascript?
如何在 javascript 中生成加密安全的随机数?
采纳答案by aaaaaaaaaaaa
You can for instance use mouse movement as seed for random numbers, read out time and mouse position whenever the onmousemove event happens, feed that data to a whitening function and you will have some first class random at hand. Though do make sure that user has moved the mouse sufficiently before you use the data.
例如,您可以使用鼠标移动作为随机数的种子,每当 onmousemove 事件发生时读出时间和鼠标位置,将该数据提供给白化函数,您将获得一些一流的随机数。尽管在使用数据之前请确保用户已充分移动鼠标。
Edit: I have myself played a bit with the concept by making a password generator, I wouldn't guarantee that my whitening function is flawless, but being constantly reseeded I'm pretty sure that it's plenty for the job: ebusiness.hopto.org/generator.htm
编辑:我通过制作密码生成器对这个概念进行了一些尝试,我不能保证我的美白功能是完美无缺的,但是不断重新播种我很确定它足以完成这项工作:ebusiness.hopto.org /generator.htm
Edit2: It now sort of works with smartphones, but only by disabling touch functionality while the entropy is gathered. Android won't work properly any other way.
Edit2:它现在有点适用于智能手机,但只能在收集熵时禁用触摸功能。Android 将无法以任何其他方式正常工作。
回答by Paul V
There's been discussion at WHATWG on adding this to the window.crypto object. You can read the discussionand check out the proposed APIand webkit bug (22049).
WHATWG 已经讨论过将其添加到 window.crypto 对象。您可以阅读讨论并查看提议的 API和 webkit 错误 (22049)。
Just tested the following code in Chrometo get a random byte:
刚刚在 Chrome 中测试了以下代码以获取随机字节:
(function(){
var buf = new Uint8Array(1);
window.crypto.getRandomValues(buf);
alert(buf[0]);
})();
回答by ZeroG
In order, I think your best bets are:
按顺序,我认为您最好的选择是:
- window.crypto.getRandomValues or window.msCrypto.getRandomValues
- The sjcl library's randomWords function (http://crypto.stanford.edu/sjcl/)
- The isaac library's random number generator (which is seeded by Math.random, so not really cryptographically secure) (https://github.com/rubycon/isaac.js)
- window.crypto.getRandomValues 或 window.msCrypto.getRandomValues
- sjcl 库的 randomWords 函数 ( http://crypto.stanford.edu/sjcl/)
- isaac 库的随机数生成器(由 Math.random 提供种子,因此不是真正的加密安全)(https://github.com/rubycon/isaac.js)
window.crypto.getRandomValues has been implemented in Chrome for a while now, and relatively recently in Firefox as well. Unfortunately, Internet Explorer 10 and before do not implement the function. IE 11 has window.msCrypto, which accomplishes the same thing. sjcl has a great random number generator seeded from mouse movements, but there's always a chance that either the mouse won't have moved sufficiently to seed the generator, or that the user is on a mobile device where there is no mouse movement whatsoever. Thus, I recommend having a fallback case where you can still get a non-secure random number if there is no choice. Here's how I've handled this:
window.crypto.getRandomValues 已经在 Chrome 中实现了一段时间,最近也在 Firefox 中实现了。遗憾的是,Internet Explorer 10 及之前版本没有实现该功能。IE 11 有 window.msCrypto,它完成了同样的事情。sjcl 有一个很好的随机数生成器,从鼠标移动开始,但总有可能是鼠标没有充分移动来生成生成器,或者用户在移动设备上,没有任何鼠标移动。因此,我建议有一个后备案例,如果别无选择,您仍然可以获得不安全的随机数。这是我处理这个问题的方法:
function GetRandomWords (wordCount) {
var randomWords;
// First we're going to try to use a built-in CSPRNG
if (window.crypto && window.crypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.crypto.getRandomValues(randomWords);
}
// Because of course IE calls it msCrypto instead of being standard
else if (window.msCrypto && window.msCrypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.msCrypto.getRandomValues(randomWords);
}
// So, no built-in functionality - bummer. If the user has wiggled the mouse enough,
// sjcl might help us out here
else if (sjcl.random.isReady()) {
randomWords = sjcl.random.randomWords(wordCount);
}
// Last resort - we'll use isaac.js to get a random number. It's seeded from Math.random(),
// so this isn't ideal, but it'll still greatly increase the space of guesses a hacker would
// have to make to crack the password.
else {
randomWords = [];
for (var i = 0; i < wordCount; i++) {
randomWords.push(isaac.rand());
}
}
return randomWords;
};
You'll need to include sjcl.js and isaac.js for that implementation, and be sure to start the sjcl entropy collector as soon as your page is loaded:
您需要为该实现包含 sjcl.js 和 isaac.js,并确保在您的页面加载后立即启动 sjcl 熵收集器:
sjcl.random.startCollectors();
sjcl is dual-licensed BSD and GPL, while isaac.js is MIT, so it's perfectly safe to use either of those in any project. As mentioned in another answer, clipperz is another option, however for whatever bizarre reason, it is licensed under the AGPL. I have yet to see anyone who seems to understand what implications that has for a JavaScript library, but I'd universally avoid it.
sjcl 是双许可的 BSD 和 GPL,而 isaac.js 是 MIT,所以在任何项目中使用它们中的任何一个都是完全安全的。正如另一个答案中提到的,clipperz 是另一种选择,但是无论出于什么奇怪的原因,它都是根据 AGPL 获得许可的。我还没有看到任何人似乎理解这对 JavaScript 库有什么影响,但我会普遍避免它。
One way to improve the code I've posted might be to store the state of the isaac random number generator in localStorage, so it isn't reseeded every time the page is loaded. Isaac will generate a random sequence, but for cryptography purposes, the seed is all-important. Seeding with Math.random is bad, but at least a little less bad if it isn't necessarily on every page load.
改进我发布的代码的一种方法可能是将 isaac 随机数生成器的状态存储在 localStorage 中,因此每次加载页面时都不会重新播种。Isaac 将生成一个随机序列,但出于密码学目的,种子非常重要。用 Math.random 播种是不好的,但如果它不一定在每个页面加载时都那么糟糕。
回答by phihag
Use window.crypto.getRandomValues
, like this:
使用window.crypto.getRandomValues
,像这样:
var random_num = new Uint8Array(2048 / 8); // 2048 = number length in bits
window.crypto.getRandomValues(random_num);
This is supported in all modern browsersand uses the operating system's random generator (e.g. /dev/urandom
). If you need IE11 compatibility, you have to use their prefixed implementation viavar crypto = window.crypto || window.msCrypto; crypto.getRandomValues(..)
though.
这在所有现代浏览器中都受支持,并使用操作系统的随机生成器(例如/dev/urandom
)。如果您需要 IE11 兼容性,则必须使用它们的前缀实现 via var crypto = window.crypto || window.msCrypto; crypto.getRandomValues(..)
。
Note that the window.crypto
API can also generate keys outright, which may be the better option.
请注意,window.crypto
API 也可以直接生成密钥,这可能是更好的选择。
回答by Kamil Kie?czewski
回答by ameer
You might want to try http://sourceforge.net/projects/clipperzlib/It has an implementation of Fortunawhich is a cryptographically secure random number generator. (Take a look at src/js/Clipperz/Crypto/PRNG.js). It appears to use the mouse as a source of randomness as well.
你可能想尝试 http://sourceforge.net/projects/clipperzlib/它有一个Fortuna的实现,它是一个加密安全的随机数生成器。(看看 src/js/Clipperz/Crypto/PRNG.js)。它似乎也使用鼠标作为随机性的来源。
回答by user2674414
First of all, you need a source of entropy. For example, movement of the mouse, password, or any other. But all of these sources are very far from random, and guarantee you 20 bits of entropy, rarely more. The next step that you need to take is to use the mechanism like "Password-Based KDF" it will make computationally difficult to distinguish data from random.
首先,你需要一个熵源。例如,鼠标、密码或任何其他的移动。但所有这些来源都远非随机,并保证你有 20 位的熵,很少更多。您需要采取的下一步是使用“基于密码的 KDF”之类的机制,这将使区分数据与随机数据在计算上变得困难。
回答by Scott Arciszewski
Many years ago, you had to implement your own random number generator and seed it with entropy collected by mouse movement and timing information. This was the Phlogiston Era of JavaScript cryptography. These days we have window.crypto
to work with.
许多年前,您必须实现自己的随机数生成器,并使用通过鼠标移动和计时信息收集的熵进行播种。这是 JavaScript 密码学的燃素时代。这几天我们要window.crypto
一起工作。
If you need a random integer, random-number-csprngis a great choice. It securely generates a series of random bytes and then converts it into an unbiased random integer.
如果您需要一个随机整数,random-number-csprng是一个不错的选择。它安全地生成一系列随机字节,然后将其转换为无偏随机整数。
const randomInt = require("random-number-csprng");
(async function() {
let random = randomInt(10, 30);
console.log(`Your random number: ${random}`);
})();
If you need a random floating point number, you'll need to do a little more work. Generally, though, secure randomness is an integer problem, not a floating point problem.
如果您需要一个随机浮点数,则需要做更多的工作。不过,一般来说,安全随机性是一个整数问题,而不是一个浮点问题。