如何从哈希中获得一个数字

我试图在node.js创build01000000 (100万)之间的随机数。 散列是:

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

随机数

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

但有时我得到的数字大于100万,我怎么能防止这个?

SimpleDRBG定义了一个简单的(不符合FIPS的)DRBG,它基本上就是使用一系列HMAC值的NIST HMAC_Generate函数。 请注意,请求1个字节,其次是另一个与同时询问2个字节是不一样的。


RandomInt类是可以使用该类中的randomBytes或Node.js的crypto模块的类。 它会创build一个范围内的随机有限数字或数字。

boundedRandomNumber函数首先计算要求的字节数,比要求的字节数多一点。 这些字节然后被转换成一个大整数,称为candidate 。 然后这个值返回,模数的界限。

while循环确保没有朝向频谱的低端倾斜,因为最高candidate值可以返回0和X之间的值,其中X <在进行模数bound之后被bound 。 在这种情况下请求更多的字节。 在目前的实现中,循环不止一次的机会不是很高,所以这些函数应该是相对有效的。


所以文件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, ie 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, ie 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); 

只要你希望使用散列来解决你的问题,你就可以:根据维基百科的说法,“…一个随机抽取器,比如一个密码散列函数,可以用来从一个非均匀的随机源中均匀分布位,尽pipe以较低的比特率。“

从好的密码散列函数输出(SHA512是您的select)中取第一个连续的五位hex数[Log2(10 ^ 6)+ 1]。 testing它是否小于或等于你的上限。 否则testing下5个hex数字。 输出也将有一个统一的分布。 20位随机数将会大于你的上限的概率是p = 48575/1048576 = 0.0463247如果在25个非重叠子集上分割128位,那么所有子集都不好的概率是p ^ 25 = 4.41 * 10 ^ -34 。 如果这不能忽略,那么计算下一个散列。 我采取了非重叠的子集为最简单的概率计算(子集独立性),但为您的任务,你可以移动一个hex数字和testing多达124个子集。