자바 스크립트에서 암호화 보안 난수를 어떻게 생성합니까?
자바 스크립트에서 암호화 보안 난수를 어떻게 생성합니까?
답변:
예를 들어 마우스 움직임을 난수에 대한 시드로 사용하고, onmousemove 이벤트가 발생할 때마다 시간과 마우스 위치를 읽고, 해당 데이터를 미백 기능에 공급하면 임의의 일류 클래스를 가질 수 있습니다. 데이터를 사용하기 전에 사용자가 마우스를 충분히 움직 였는지 확인하십시오.
편집 : 나는 암호 생성기를 만들어서 개념을 조금 가지고 놀았습니다. 내 미백 기능이 완벽하다는 것을 보장하지는 않지만 지속적으로 다시 시드되는 것은 작업에 충분하다고 확신합니다 : ebusiness.hopto.org /generator.htm
Edit2 : 이제 스마트 폰에서 작동하지만 엔트로피가 수집되는 동안 터치 기능을 비활성화하는 경우에만 작동합니다. Android는 다른 방식으로 제대로 작동하지 않습니다.
.password
span
복사 / 붙여 넣기 / 조작을 쉽게하기 위해 해당 문자열이 각 태그 사이에 삽입되도록하는 구분자 필드를 추가합니다 . 예를 들어 현재 생성 된 문자열을 복사하여 붙여 넣으면 하나의 긴 문자열로 붙여 넣습니다.
순서대로, 최선의 방법은 다음과 같습니다.
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은 이중 라이선스 BSD 및 GPL이고 isaac.js는 MIT이므로 모든 프로젝트에서 둘 중 하나를 사용하는 것이 완벽하게 안전합니다. 다른 답변에서 언급했듯이 clipperz는 또 다른 옵션이지만 기괴한 이유가 무엇이든 AGPL에 따라 라이센스가 부여됩니다. JavaScript 라이브러리에 어떤 의미가 있는지 이해하는 사람은 아직 보지 못했지만 보편적으로 피하고 싶습니다.
내가 게시 한 코드를 개선하는 한 가지 방법은 isaac 난수 생성기의 상태를 localStorage에 저장하는 것이므로 페이지가로드 될 때마다 다시 시드되지 않습니다. Isaac은 임의의 시퀀스를 생성하지만 암호화를 위해 시드가 매우 중요합니다. Math.random으로 시드하는 것은 나쁘지만 모든 페이지로드에 반드시 필요한 것은 아니라면 적어도 조금 덜 나쁩니다.
random16byteHex.advance(Math.floor(event.keyCode/4));
몇 밀리 초 동안 난수를 앞으로 건너 뛰는 역할도합니다. 그러면 해당 브라우저 앱에서 사용되는 isaac 랜덤이 사용자 입력과 하드웨어 / 브라우저 속도에 따라 달라 지므로 추측하기가 매우 어렵습니다.
touchmove
( pull # 151 ) 및 devicemotion
( pull # 79 ) 에서 수집되므로 모바일 장치에서 잘 작동합니다 .
다음 window.crypto.getRandomValues
과 같이 사용하십시오 .
var random_num = new Uint8Array(2048 / 8); // 2048 = number length in bits
window.crypto.getRandomValues(random_num);
이는 모든 최신 브라우저에서 지원되며 운영 체제의 임의 생성기 (예 :) 를 사용합니다 /dev/urandom
. IE11 호환성이 필요한 경우에는 접두사가 붙은 구현을 사용해야합니다 var crypto = window.crypto || window.msCrypto; crypto.getRandomValues(..)
.
있습니다 window.crypto
API는 또한 수 크게 키를 생성 더 좋은 옵션이 될 수있다.
http://sourceforge.net/projects/clipperzlib/ 시도해 볼 수 있습니다 . 암호화 보안 난수 생성기 인 Fortuna 를 구현했습니다 . (src / js / Clipperz / Crypto / PRNG.js를보세요). 마우스를 임의의 소스로 사용하는 것으로 보입니다.
우선 엔트로피 소스가 필요합니다. 예를 들어, 마우스, 암호 또는 기타 이동. 그러나 이러한 모든 소스는 무작위와는 거리가 멀고 거의 20 비트의 엔트로피를 보장합니다. 다음 단계는 "암호 기반 KDF"와 같은 메커니즘을 사용하는 것입니다. 이렇게하면 데이터를 무작위와 구별하기가 계산적으로 어렵습니다.
수년 전에는 자신 만의 난수 생성기를 구현하고 마우스 움직임과 타이밍 정보로 수집 된 엔트로피를 시드해야했습니다. 이것은 JavaScript 암호화의 플로지스톤 시대였습니다. 요즘 우리는 window.crypto
함께 일해야 합니다.
당신이 임의의 필요한 경우 정수를 , 난수-CSPRNG는 좋은 선택이 될 것입니다. 일련의 임의 바이트를 안전하게 생성 한 다음이를 편향되지 않은 임의의 정수로 변환합니다.
const randomInt = require("random-number-csprng");
(async function() {
let random = randomInt(10, 30);
console.log(`Your random number: ${random}`);
})();
임의의 부동 소수점 숫자가 필요한 경우 조금 더 작업을해야합니다. 그러나 일반적으로 보안 임의성은 부동 소수점 문제가 아니라 정수 문제입니다.