IT TIP

자바 스크립트에서 난수를 확보 하시겠습니까?

itqueen 2020. 10. 16. 19:20
반응형

자바 스크립트에서 난수를 확보 하시겠습니까?


자바 스크립트에서 암호화 보안 난수를 어떻게 생성합니까?


예를 들어 마우스 움직임을 난수에 대한 시드로 사용하고, onmousemove 이벤트가 발생할 때마다 시간과 마우스 위치를 읽고, 해당 데이터를 미백 기능에 공급하면 임의의 일류 클래스를 가질 수 있습니다. 데이터를 사용하기 전에 사용자가 마우스를 충분히 움직 였는지 확인하십시오.

편집 : 나는 암호 생성기를 만들어서 개념을 조금 가지고 놀았습니다. 내 미백 기능이 흠 잡을 데 없다는 것을 보장하지는 않지만 지속적으로 다시 시드되는 것은 작업에 충분하다고 확신합니다 : ebusiness.hopto.org /generator.htm

Edit2 : 이제 일종의 스마트 폰에서 작동하지만 엔트로피가 수집되는 동안 터치 기능을 비활성화해야합니다. Android는 다른 방법으로 제대로 작동하지 않습니다.


window.crypto 객체에 이것을 추가하는 것에 대해 WHATWG에서 논의되었습니다. 당신이 읽을 수있는 논의를 하고 체크 아웃 제안 API 와 웹킷 버그 (22,049)을.

임의의 바이트를 얻기 위해 Chrome 에서 다음 코드 테스트했습니다 .

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


순서대로, 최선의 방법은 다음과 같습니다.

  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;
};

해당 구현을 위해 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.

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.


Use window.crypto.getRandomValues, like this:

var random_num = new Uint8Array(2048 / 8); // 2048 = number length in bits
window.crypto.getRandomValues(random_num);

This is supported in all modern browsers and 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.

Note that the window.crypto API can also generate keys outright, which may be the better option.


You might want to try http://sourceforge.net/projects/clipperzlib/ It has an implementation of Fortuna which 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.


to get cryptographic strong number from range [0, 1) (similar to Math.random()) use crypto:

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

console.log( random() );


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.

참고URL : https://stackoverflow.com/questions/4083204/secure-random-numbers-in-javascript

반응형