암호화 라이브러리를 사용하면 라이브러리에서 여러 개의 임의 바이트를 제공하도록 요청할 수 있습니다. 문제는이 바이트가 각각 0에서 255까지의 숫자 (포함)이므로 균일하게 분산 된 결과를 만드는 것이 그렇게 간단하지 않다는 것입니다.
내 말은 다음과 같습니다.
이 함수는 10, 100, ... 10 ^ b 인 숫자 N을 받고, 여기서 b는 1과 8 사이의 숫자 (더 클 수 있지만 더 큰 것은 필요하지 않음)이고 0과 사이의 숫자를 반환합니다. 주어진 숫자 (주어진 숫자를 포함하지 않음), 즉 N이 100이면 함수의 결과는 0에서 99까지이고 N이 10이면 결과는 0에서 9까지입니다.
Math.random을 사용하고 N을 곱한 다음 floor를 사용하여 난수를 만들 수 있습니다. 그러나 Math.random은 암호 학적으로 안전하지 않으므로 임의로 생성 된 2 ^ 8m 숫자를 사용하여 수행해야합니다. 여기서 m은 crypto.randomBytes에 주어진 바이트 수입니다.
분명히 작동하는 간단한 기능을 만들었습니다. 그러나 난수에 약간의 편향을 유도하는 것이 상당히 쉽다는 것을 알고 있으며 프로젝트에 다소 중요하기 때문에 검증을 받고 싶습니다.
genera_aleatorio_residuo_potencia10 : function (n, cb) {
var digitos = Math.log(n) / Math.LN10;
var extra_base2 = digitos > 8 ? digitos - 8 : 0;
if (Math.floor(digitos + .4) - digitos > 0.00000001) {
return cb("Numero no es potencia de 10 (10, 100, 1000...)", null);
}
digitos = Math.round(digitos);
async.parallel({
r1 : crypto_helper.generador_random_bytes(1),
r2 : crypto_helper.generador_random_bytes(1)
}, function (err, res) {
if (err) {
return cb(err, null);
}
var r1 = res.r1[0] + 1;
var r2 = res.r2[0] + 1;
var aleatorio = (Math.pow(5, digitos) - 1) * Math.pow(2, extra_base2) * r1 + r2;
cb(null, aleatorio % n);
});
}
말할 필요도없이 : crypto_helper.generador_random_bytes는 비동기 라이브러리를 더 친숙하게 만들기 위해 자주 사용하는 node.js의 crypto.randomBytes의 래퍼입니다.
Math.pow (5, digitos) 및 Math.pow (2, extra_base2)를 사용하는 이유는 N과 256 사이의 최소 공배수 때문입니다. 실제로 n은 100000000보다 크지 않으므로 Math.pow ( 2, extra_base2)는 우리 제품에서 사용해서는 안되지만 다른 사람들에게도 이해가되는지 확인하고 싶습니다.
Java의 SecureRandom.nextInt (int)가 여기에서 수행하는 작업을 간단히 모방하여 훌륭한 솔루션을 찾았습니다. SecureRandom.nextInt (int) 코드를 작성할 수있는 즉시 코드를 게시합니다 (현재 바쁘다). 제안 된 솔루션에 편향이 있음을 확인했기 때문에 개발 한 코드를 사용할 계획입니다 (전혀 허용되지 않음).
다음은 JDK 코드의 적응입니다. 31 비트 숫자에 대한 제한에 주목하십시오. JS가 32 비트로 2의 보수에 대해 모든 비트 연산을 수행한다는 것을 깨달았 기 때문입니다. 나는 그것을 사용하지 않을 것이기 때문에 2의 거듭 제곱에 대한 특별한 경우를 구현하지 않았습니다. 해결책은 일반적으로 10의 거듭 제곱뿐 아니라 10의 거듭 제곱을위한 것입니다. 10 진법을 사용하는 숫자에 대한 더 나은 솔루션이 있어야합니다. 다른 사람들이 더 쉽게 사용할 수 있도록 라이브러리를 사용하지 않고 영어로 만들도록 코드를 다시 작성했습니다.
var crypto_random_number_range = function (n, cb) {
//result is a number from 0 a n-1
//Javascript works with 32 bits for bitwise operations but these are signed (2-complement), so it is good to limit the size of n
if (n <= 0 || n > 2147483647) {
return cb("n must be larger than 0 and smaller than 2147483647", null);
}
var bits, val;
async.doWhilst(
function (cb2) {
crypto.randomBytes(4, function (err, rbytes) {
if (err) {
return cb2(err);
}
bits = ((rbytes[3] & 0x7f) << 24) +
(rbytes[2] << 16) + (rbytes[1] << 8) + rbytes[0];
val = bits % n;
cb2();
});
}, function () {
return (bits - val + (n-1)) < 0;
}, function (err) {
if (err) {
return cb(err, null);
}
return cb(null, val);
}
);
}
몇 번의 테스트를했지만 제대로 작동하는 것 같습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다