2014-10-18 120 views
2

我试图在node.js之间的01000000(100万)之间创建随机数。哈希是:如何从哈希中获得数字

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

随机数

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

但有时我得到超过100万的大数字,我怎样才能避免这种情况?

+0

你为什么使用createHmac()?有更好的工具,这不是createHmac()的用途。试试crypto.randomBytes() – dandavis 2014-10-18 19:05:25

+0

你能指点我其他工具吗?我正在使用哈希函数,因为我需要证明这个数字不是由我或某人操纵的。 – Lazy 2014-10-18 19:07:56

+1

如果你想要一个散列,使用散列,就像md5或更好的东西,但我不会得到随机部分进来的地方... – dandavis 2014-10-18 19:10:11

回答

1

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


的RandomInt类是可以从类或从crypto模块Node.js的的使用两randomBytes类它创建任何随机有限数字或范围内的数字。

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

while循环确保没有偏向光谱的低端,因为最高的candidate值可能会返回介于0和X之间的值,其中X <在执行模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, 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'都是很酷的。 – 2014-10-19 02:43:00

+0

在我的答案中修正了最终测试,我可能应该在那里使用'var'关键字。 – 2014-10-19 11:58:35

+0

我猜如果你想要一个浮点数,只需要选择一个特定的精度然后除以正确的数量就是一个好主意...... – 2014-10-19 14:20:42

1

只要你想使用散列您的问题,您可以:аccording维基百科”。 ..一个随机抽取器,比如一个密码散列函数,可以用来接近来自非均匀随机源的比特的均匀分布,尽管在更低的比特率“。

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