在javascript中保护随机数?

Kyl*_*yle 76 javascript cryptography

如何在javascript中生成加密安全随机数?

Pau*_*l V 59

WHATWG已经讨论过将其添加到window.crypto对象中.您可以阅读讨论并查看建议的API和webkit错误(22049).

刚刚在Chrome中测试了以下代码以获取随机字节:

(function(){
  var buf = new Uint8Array(1);
  window.crypto.getRandomValues(buf);
  alert(buf[0]);
})();
Run Code Online (Sandbox Code Playgroud)

  • 至于我的阅读作品很棒的Firefox和Chrome,而不是IE浏览器. (2认同)

Zer*_*roG 27

按顺序,我认为你最好的赌注是:

  1. window.crypto.getRandomValues或window.msCrypto.getRandomValues
  2. sjcl库的randomWords函数(http://crypto.stanford.edu/sjcl/)
  3. isaac库的随机数生成器(由Math.random播种,因此不具有加密安全性)(https://github.com/rubycon/isaac.js)

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;
};
Run Code Online (Sandbox Code Playgroud)

您需要为该实现包含sjcl.js和isaac.js,并确保在加载页面后立即启动sjcl熵收集器:

sjcl.random.startCollectors();
Run Code Online (Sandbox Code Playgroud)

sjcl是双重许可的BSD和GPL,而isaac.js是MIT,因此在任何项目中使用其中任何一个都是完全安全的.正如另一个答案所述,clipperz是另一种选择,但无论出于什么奇怪的原因,它都是根据AGPL许可的.我还没有看到任何人似乎理解对JavaScript库有什么影响,但我会普遍避免它.

改进我发布的代码的一种方法可能是将isaac随机数生成器的状态存储在localStorage中,因此每次加载页面时都不会重新插入.Isaac将生成一个随机序列,但是出于加密目的,种子是非常重要的.使用Math.random播种是不好的,但如果不一定在每个页面加载上,则至少要少一点.


aaa*_*aaa 23

例如,您可以使用鼠标移动作为随机数的种子,每当onmousemove事件发生时读出时间和鼠标位置,将该数据提供给美白功能,您将获得一些随机的随机数.尽管在使用数据之前确保用户已充分移动鼠标.

编辑:我自己通过制作一个密码生成器来玩这个概念,我不能保证我的美白功能完美无缺,但不断重新接种我很确定这个工作很充分:ebusiness.hopto.org /generator.htm

Edit2:它现在可以与智能手机配合使用,但只能通过在收集熵时禁用触摸功能.Android将无法以任何其他方式正常工作.

  • 这是一个带有BSD许可证的加密库,以及一个随机数生成器:http://crypto.stanford.edu/sjcl/ (11认同)

phi*_*hag 12

使用window.crypto.getRandomValues,像这样:

var random_num = new Uint8Array(2048 / 8); // 2048 = number length in bits
window.crypto.getRandomValues(random_num);
Run Code Online (Sandbox Code Playgroud)

在所有现代浏览器中都受支持,并使用操作系统的随机生成器(例如/dev/urandom).如果你需要IE11兼容性,你必须使用他们的前缀实现var crypto = window.crypto || window.msCrypto; crypto.getRandomValues(..).

请注意,window.cryptoAPI也可以直接生成密钥,这可能是更好的选择.

  • @Sid这听起来像一个很好的问题.[问一下](http://stackoverflow.com/questions/ask)! (2认同)
  • @phihag:已经做过,直到现在都没有答案.http://stackoverflow.com/questions/41437492/how-to-use-window-crypto-getrandomvalues-to-get-random-values-in-a-specific-rang (2认同)

Kam*_*ski 6

要从范围[0, 1)(类似于Math.random())中获取加密强数,请使用crypto

let random = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32;

console.log( random() );
Run Code Online (Sandbox Code Playgroud)