2014-10-18 125 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個子集。