Nasıl node.js KİMLİĞİ olarak kullanmak için rastgele SHA1 hash oluşturmak için?
Bu hat node.js sha1 için bir kimlik oluşturmak için kullanıyorum:
crypto.createHash('sha1').digest('hex');
Sorun aynı kimliği her zaman dönüyor.
Bu veritabanı belge numarası olarak kullanabilirsiniz böylece rastgele bir kimliği her zaman oluşturmak mümkün mü?
CEVAP
Daha fazla entropi 14,615,016,373,300,259,879,912,540,705,229 x
crypto.randomBytes kullanmanızı tavsiye ediyorum. sha1
ama kimliği amaçlar için, daha hızlı ve adil olarak değil"". rasgele
var id = crypto.randomBytes(20).toString('hex');
//=> bb5dc8842ca31d4603d6aa11448d1654
Sonuç dizesi rasgele bayt oluşturmak için iki kat daha uzun olacak; her bayt 2 karakter hex kodlanmış. 20 bayt hex 40 karakter olacak.
20 bayt kullanarak, ** 16 yaşında ya var1,461,501,637,330,902,918,203,684,832,716,283,019,655,932,542,976benzersiz çıkış değerleri. BuaynıSHA1 160 bit (20 byte) Olası çıkışları için.
Bunu bilerek, bize 17 ** rasgele bayt bizim için gerçekten çok anlamlı değildir. İki kez ölmek haddeleme ama sadece ikinci rulo;, 6 rulo Olası sonucu her ne olursa olsun kabul etmek gibi bir şey, ilk rulo yeterlidir.
Neden bu daha mı iyi?
Bu daha iyi anlamak için, biz ilk karma fonksiyonların nasıl çalıştığını anlamak zorunda. Fonksiyonlar (SHA1 dahil) karma hep aynı giriş verilirse aynı çıktıyı üretecektir.
Kimliklerini oluşturmak istiyoruz ama rastgele girdiğimiz bir yazı tura ile oluşturulur söylüyorlar. "heads"
"tails"
var
% echo -n "heads" | shasum
c25dda249cdece9d908cc33adcd16aa05e20290f -
% echo -n "tails" | shasum
71ac9eed6a76a285ae035fe84a251d56ae9485a4 -
"heads"
tekrar gelirse, SHA1 çıktıaynıilk seferinde olduğu gibi
% echo -n "heads" | shasum
c25dda249cdece9d908cc33adcd16aa05e20290f -
Tamam, yazı tura atmak, böylece biz sadece 2 Olası çıkışları var çünkü büyük rasgele bir KİMLİK oluşturucu değildir.
Eğer 6 taraflı kalıp standart kullanırsak, 6 Olası girişler var. Kaç Olası SHA1 çıkışları sanırım? 6!
input => (sha1) => output
1 => 356a192b7913b04c54574d18c28d46e6395428ab
2 => da4b9237bacccdf19c0760cab7aec4a8359010b0
3 => 77de68daecd823babbb58edb1c8e14d7106e83bb
4 => 1b6453892473a467d07372d45eb05abc2031647a
5 => ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
6 => c1dfd96eea8cc2b62785275bca38ac261256e278
Kolay sadece bizim işlevin çıktı çünkü düşünerek kendimizi kandırırızgörünüyorçok rastgele, o kadarçok rastgele.
İkimiz de bir yazı-tura veya 6-taraflı kalıp Olası SHA1 sonuçları (KİMLİĞİ için kullandığımız değer) çok az olduğu için kötü rasgele kimliği bir jeneratör yapmak konusunda hemfikirler. Ama eğer çok fazla çıkışları olan bir şey kullansak nasıl olur? Milisaniye ile bir zaman damgası gibi? Veya JavaScript Math.random
? Hatta birkombinasyonuiki? o!
Bakalım kaç tane almak istiyorsunuz ... hesaplamak
Milisaniye zaman damgası ile bir teklik
(new Date()).valueOf().toString()
, kullanırken 13 karakterlik bir sayı (örneğin, 1375369309741
) alıyoruz. Ancak, bu yana sırayla numara güncelleme (milisaniye başına bir kez) çıkışlar, hemen hemen her zaman aynıdır. Bir bakalım
for (var i=0; i<10; i ) {
console.log((new Date()).valueOf().toString());
}
console.log("OMG so not random");
// 1375369431838
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431839
// 1375369431840
// 1375369431840
// OMG so not random
Adil olmak gerekirse, karşılaştırma amacıylaverilen bir dakika içinde(cömert operasyon yürütme zamanı), 60*1000
60000
tekil olacak.
Math.random
teklik
JavaScript 64-bit kayan nokta sayılarını temsil eder, çünkü Math.random
, kullanırken, uzunluğu ile bir sayı arasında herhangi bir yerde 13 ve 24 karakter uzunluğunda alacaksın. Uzun bir sonucu daha fazla entropi anlamına gelir daha fazla basamak anlamına gelir. İlk olarak, en olası uzunluğu olduğunu öğrenmek için ihtiyacımız var.
Aşağıdaki komut dosyası en olası olduğunu belirlemek olacaktır. 1 milyon rastgele sayılar üreten bir sayaç her sayı .length
göre artan isteriz.
// get distribution
var counts = [], rand, len;
for (var i=0; i<1000000; i ) {
rand = Math.random();
len = String(rand).length;
if (counts[len] === undefined) counts[len] = 0;
counts[len] = 1;
}
// calculate % frequency
var freq = counts.map(function(n) { return n/1000000 *100 });
1 milyon tarafından her sayaç bölerek, numara uzunluğu Math.random
döndü olasılığını elde ederiz.
len frequency(%)
------------------
13 0.0004
14 0.0066
15 0.0654
16 0.6768
17 6.6703
18 61.133 <- highest probability
19 28.089 <- second highest probability
20 3.0287
21 0.2989
22 0.0262
23 0.0040
24 0.0004
Tamamen doğru olmasa da, cömert olalım ve 19 karakterlik rastgele bir çıkış; 0.1234567890123456789
olsun diyorum. İlk karakter her zaman 0
17 rasgele karakterler alıyoruz yani gerçekten .
, olacaktır. 10^17
1
(Olası 0
; notlara bakın) bize bırakıyor bu ya100,000,000,000,000,001tekil.
Kaç tane rasgele girişler oluşturabilir miyiz?
Tamam, milisaniyelik bir zaman damgası ve Math.random
için sonuç sayısını hesapladık
60,000 (timestamp)
100,000,000,000,000,001 (Math.random)
-------------------------
100,000,000,000,060,001
Bu 100,000,000,000,060,001 taraflı tek bir kalıp. Veya, bu sayı daha fazla yapmak insanca sindirilebilir, bu periyodik olarak aynı sayıda kabaca10x50-taraflı zar. Kulağa hoş geliyor, değil mi?
SHA1 20-bayt bir değer, 256^20 olası sonuçlar üretir. Gerçekten tam potansiyeline için SHA1 kullanmıyoruz. Peki ne kadar kullanıyoruz?
node> 100000000000060001 / (Math.pow(256,20)) * 100
Milisaniyelik bir zaman damgası ve Matematik.rastgele kullanır sadece 6.84 e-30 SHA1 160 bit % potansiyel!
generator sha1 potential used
-----------------------------------------------------------------------------
crypto.randomBytes(20) 100%
Date() Math.random() 0.00000000000000000000000000000684%
6-sided die 0.000000000000000000000000000000000000000000000411%
A coin 0.000000000000000000000000000000000000000000000137%
Aman Tanrım! Şu sıfırlara bak. Ne kadar iyi crypto.randomBytes(20)
?14,615,016,373,300,259,879,912,540,705,229kat daha iyi.
Sıfır 1
ve sıklığı hakkında notlar
1
merak ediyorsan Math.random
hesap var 1 yok 50 ** daha olası benzersiz bir sonuca dönmek mümkün.
Aşağıda yaşanan tartışma dayalı, 0
gelip bir frekansı merak ettim. Burada küçük bir script, random_zero.js
, bazı veriler elde ettim
#!/usr/bin/env node
var count = 0;
while (Math.random() !== 0) count ;
console.log(count);
Daha sonra, 4 iş parçacığı (4 çekirdekli işlemci var), çıktıyı bir dosyaya ekleme yaptım
$ yes | xargs -n 1 -P 4 node random_zero.js >> zeroes.txt
Bir 0
bu zor çıkıyor. 100 values kaydedildikten sonra, ortalama oldu
13,164,854,823ortasında bir 0
Serin! Daha fazla araştırma ise bu sayı on-par v8 Math.random
uygulama tekdüze dağılıma sahip olup olmadığını öğrenmek için gerekli olacaktır
Nasıl node.js Kripto HMAC-SHA1 hash ol...
Nasıl en iyi Ruby rastgele bir dize ol...
Nasıl C rastgele bir sayı oluşturmak i...
Algoritma rastgele estetik olarak hoş ...
Nasıl bir şablon motoru olarak undersc...