2014-10-18 4 views
2

01000000 (1 백만) 사이의 임의의 숫자를 node.js에 만들려고합니다.해시 번호를 얻는 방법

var hash = crypto.createHmac('sha512', "value").update("another value").digest('hex'); 
//d89c8a02a8b4e2461eeddcc3d8e85f2dfdab62968a329840ec5df2c0be2852eb9321cb35ff8fd5f43e97857a618d35edf9ba7fff56319c56eae4f8509f02e7eb 

난수

var number = parseInt(hash.substring(0, 5), 16); // 887240 

하지만 가끔은 내가이를 방지 할 수있는 방법, 1,000,000보다 큰 숫자를 받고 있어요 : 해시입니까?

+0

왜 createHmac()를 사용하고 있습니까? 더 나은 도구가 있고, 이것은 createHmac()가 필요한 것이 아닙니다. try crypto.randomBytes() – dandavis

+0

다른 도구를 가르쳐 주시겠습니까? 나 또는이 숫자가 나 또는 누군가에 의해 조작되지 않는다는 것을 증명해야하기 때문에 해시 함수를 사용하고 있습니다. – Lazy

+1

해시를 원한다면 md5 또는 더 나은 것과 같은 해시를 사용하십시오. 그러나 무작위 부분이 들어오는 곳을 얻지 못합니다 ... – dandavis

답변

1

SimpleDRBG는 기본적으로 HMAC 값의 체인을 사용하는 NIST HMAC_Generate 함수 인 단순한 (FIPS와 호환되지 않는) DRBG를 정의합니다. 1 바이트 요청 후 다른 요청은 동시에 2 바이트를 요구하는 것과 같지 않습니다.


하는 randomInt 클래스는 클래스 또는 Node.js.의 crypto 모듈로부터 어느 randomBytes를 사용할 수있는 클래스 임의의 바운드 된 숫자 또는 범위의 숫자를 만듭니다.

boundedRandomNumber 함수는 먼저 요청 바이트 수를 계산합니다.이 바이트는 필요한 바이트 수보다 조금 더 높습니다. 이 바이트는 candidate이라는 큰 정수로 변환됩니다. 그런 다음이 값이 반환되고 계수가 계산됩니다.

while 루프는 최저 candidate 값이 0과 X 사이의 값을 반환 할 수 있으므로 스펙트럼 하단의 왜곡이 없는지 확인합니다. bound을 수행 한 후 X <이 바인딩됩니다. 이 경우 더 많은 바이트가 요청됩니다. 현재 구현에서는 루프가 두 번 이상 수행 될 가능성이 높지 않으므로 이러한 함수는 상대적으로 효율적이어야합니다.


그래서 simpledrbg.js 포함해야 파일 :

crypto = require('crypto'); 

exports.SimpleDRBG = function (k) { 
    this.k = k; 
    this.v = new Buffer(0); 
} 

exports.SimpleDRBG.prototype.randomBytes = function(bytes) { 

    var result = new Buffer(0); 
    var generatedBytes = 0; 
    while (generatedBytes < bytes) { 
     this.hmac = crypto.createHmac('sha512', this.k); 
     this.hmac.update(this.v); 
     this.v = this.hmac.digest(); 
     var tocopy = Math.min(this.v.length, bytes - generatedBytes); 
     if (tocopy == this.v.length) { 
      result = Buffer.concat([result, this.v]); 
     } else { 
      var vslice = this.v.slice(0, tocopy); 
      result = Buffer.concat([result, vslice]); 
     } 
     generatedBytes += tocopy; 
    } 

    return result; 
} 

randomint.js이 포함되어 있어야합니다

crypto = require('crypto'), 
bigint = require('bigint'); 
drbg = require('./simpledrbg'); 

function RandomInt(randomizer) { 
    this.randomizer = randomizer; 
} 

/** 
* Returns a bounded random number, i.e. in the range [0..bound). 
* The highest possible value that may be returned is bound - 1. 
* Use boundedRandomNumber (bound + 1) if you want the bound value to 
* be the highest possible value that can be returned. 
*/ 
RandomInt.prototype.boundedRandomNumber = function (bound) { 
    BYTE_SIZE = 8; 

    bigBound = bigint(bound); 
    bigBoundLen = bigint(bigBound.bitLength()); 

    // request a higher number of bytes just to be sure that 
    // the candidates are selected with high probability 

    bytesToRequest = bigBoundLen.add(BYTE_SIZE).sub(1).div(BYTE_SIZE).add(1); 

    // bigBound won't fit an integral number of times in the max value returned 
    // so if it is higher than the largest n times bigBound, we need to try 
    // again 
    maxCandidateExcl = bigint(0x100).pow(bytesToRequest).div(bigBound).mul(bigBound); 

    // just an assignment that will skip the initial test 
    candidate = maxCandidateExcl; 
    while (candidate.ge(maxCandidateExcl)) { 
     bytes = this.randomizer.randomBytes(bytesToRequest.toNumber()); 
     candidate = bigint.fromBuffer(bytes); 
    } 

    // return the well distributed candidate % bound 
    return candidate.mod(bigBound).toNumber(); 
} 

/** 
* Returns a ranged random number, i.e. in the range [lowerBound..upperBound). 
* The highest possible value that may be returned is upperBound - 1. 
* Use rangedRandomNumber (lowerBound, upperBound + 1) if you want the upperBound value to 
* be the highest possible value that can be returned. 
*/ 
RandomInt.prototype.rangedRandomNumber = function (lowerBound, upperBound) { 
    return lowerBound + boundedRandomNumber (upperBound - lowerBound); 
} 

var randomIntTRNG = new RandomInt(crypto); 
var testTRNG = randomIntTRNG.boundedRandomNumber(1000000); 
console.log(testTRNG); 

var randomIntDRNG = new RandomInt(new drbg.SimpleDRBG('seed')); 
var testDRNG = randomIntDRNG.boundedRandomNumber(1000000); 
console.log(testDRNG); 
+0

매우 흥미로운 모듈/클래스/객체/함수 시스템 JavaScript가 있습니다. 다시 한번,'SimpleDRBG' 인스턴스 나 전체 모듈'crypto '를 전달할 수 있다는 것은 멋진 일입니다. –

+0

제 대답에 최종 테스트가 고정되었으므로 여기에'var' 키워드를 사용해야합니다. –

+0

나는 부동 소수점을 원한다면 특정 정밀도를 선택한 다음 적당한 양으로 나누는 것이 좋은 생각 일 것이라고 생각합니다 ... –

1

을 즉시이 문제는 수에 대한 해시를 사용하여 원하는대로 : 위키 백과에 аccording ". .. 암호 해시 함수와 같은 임의성 추출기를 사용하여 비 균일하게 임의의 소스에서 비트의 균일 한 분포에 접근 할 수 있지만 낮은 비트 전송률. "

좋은 암호 해시 함수 출력 (SHA512는 선택 사항)에서 첫 번째 순차 5 자리 16 진수 [Log2 (10^6) +1]을 가져옵니다. 상한보다 작거나 같은지 테스트하십시오. 다음 5 자리 16 진수를 테스트합니다. 산출은 또한 일정한 배급을 가지고있을 것이다. 20 비트 난수가 상한값보다 커질 확률 p = 48575/1048576 = 0.0463247 중복되지 않은 25 개의 부분 집합에 128 자리를 나눠 넣으면 모든 부분 집합이 나쁜 확률은 p^25 = 4.41 * 10^-34. 이것이 무시할 수없는 경우 다음 해시를 계산하십시오. 가장 쉬운 확률 계산을 위해 (서브셋 독립성을 위해) 중첩되지 않은 부분 집합을 가져 왔지만 작업의 경우 1 진수 자리로 이동하고 124 개의 하위 집합으로 테스트 할 수 있습니다.