source

node.js에서 ID로 사용할 랜덤 SHA1 해시를 생성하는 방법?

lovecheck 2023. 10. 14. 10:19
반응형

node.js에서 ID로 사용할 랜덤 SHA1 해시를 생성하는 방법?

node.js에 대한 sha1 ID를 생성하기 위해 이 줄을 사용합니다.

crypto.createHash('sha1').digest('hex');

문제는 매번 똑같은 아이디를 돌려준다는 것입니다.

데이터베이스 문서 id로 사용할 수 있도록 매번 랜덤 id를 생성할 수 있습니까?

243,583,606,221,817,150,598,111,409배 더 많은 엔트로피

crypto.randomBytes를 사용하는 것을 추천합니다.그런거 아냐.sha1"" 를 는합니다.

var id = crypto.randomBytes(20).toString('hex');
//=> f26d60305dae929ef8640a75e70dd78ab809cfe9

결과 문자열은 생성한 임의 바이트보다 두 배 더 길며, 각 바이트는 2자이고, 20바이트는 40자의 16진수가 됩니다.

우리는 20바이트를 사용해서.256^20또는 1,461,501,637,330,902,918,203,684,832,716,283,019,655,932,542,976개의 고유 출력 값.이는 SHA1의 160비트(20바이트) 출력과 동일합니다.

가 에 은 큰shasum우리의 무작위 바이트들.다이를 두 번 굴리되 두 번째 롤만 받아들이는 것과 같습니다. 무슨 일이 있어도 각 롤마다 6개의 가능한 결과가 있으므로 첫 번째 롤이면 충분합니다.


왜 이게 더 좋습니까?

이것이 더 나은 이유를 이해하려면 먼저 해시 기능이 어떻게 작동하는지 이해해야 합니다.해싱 기능(SHA1 포함)은 동일한 입력이 주어지면 항상 동일한 출력을 생성합니다.

ID를 생성하고 싶지만 동전 던지기를 통해 임의 입력이 생성된다고 가정합니다.우리는 가지고 있다."heads"아니면"tails"

% echo -n "heads" | shasum
c25dda249cdece9d908cc33adcd16aa05e20290f  -

% echo -n "tails" | shasum
71ac9eed6a76a285ae035fe84a251d56ae9485a4  -

한다면"heads"SHA1 출력이 처음과 동일하게 다시 나타납니다.

% echo -n "heads" | shasum
c25dda249cdece9d908cc33adcd16aa05e20290f  -

좋아요, 그럼 동전 던지기는 가능한 출력이 2개밖에 없기 때문에 좋은 랜덤 ID 생성기가 아닙니다.

표준 6면 다이를 사용하면 6개의 입력이 가능합니다.SHA1 출력이 얼마나 되는지 맞춰보세요. 6!

input => (sha1) => output
1 => 356a192b7913b04c54574d18c28d46e6395428ab
2 => da4b9237bacccdf19c0760cab7aec4a8359010b0
3 => 77de68daecd823babbb58edb1c8e14d7106e83bb
4 => 1b6453892473a467d07372d45eb05abc2031647a
5 => ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4
6 => c1dfd96eea8cc2b62785275bca38ac261256e278

우리 기능의 출력이 매우 무작위해 보인다는 이유만으로 우리 자신을 착각하기 쉽습니다.

가능한 SHA1 결과(ID에 사용하는 값)가 매우 적기 때문에 코인 토스 또는 6면 다이가 나쁜 랜덤 ID 생성기가 될 것이라는 데 우리 둘 다 동의합니다.하지만 출력이 훨씬 더 많은 것을 사용한다면 어떨까요?밀리초 타임스탬프 같은 거?아니면 자바스크립트의Math.random? 아니면 그 둘의 조합이라도?!

몇 개의 고유 ID를 얻을 수 있는지 계산해 보겠습니다.


밀리초가 있는 타임스탬프의 고유성

.(new Date()).valueOf().toString() , 13 (,1375369309741그러나 이는 순차적으로 업데이트되는 숫자이기 때문에(밀리초당 1회) 출력은 거의 항상 동일합니다.번 볼까요?

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

공정하게, 비교를 위해, 주어진 1분(후한 작업 실행 시간)에, 당신은 다음을 가질 것입니다.60*1000아니면60000특이한 점들


함의 함.Math.random

를 할 때,Math.random수 있습니다.가 64 가 13 24 에서입니다.결과가 길수록 숫자가 많아져 엔트로피가 높아집니다.우선 어떤 길이가 가장 가능성이 높은지 알아봐야 합니다.

아래 스크립트를 통해 어떤 길이가 가장 가능성이 높은지 결정할 것입니다.를 생성하고다 100합니다..length각각의 숫자의

// 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 });

각 를 100 에서 수 있습니다.Math.random.

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

비록 의 랜덤 하자, , 19 ,0.1234567890123456789 . . .0그리고..로 17명의 만 수 .이것은 우리에게 남습니다.10^17 +1한 경우하면)0; 아래 참고사항 참조) 또는 100,000,000,000,000,000,0001개의 고유사항을 참조하십시오.


그렇다면 얼마나 많은 임의의 입력을 생성할 수 있습니까?

와 에 Math.random

      100,000,000,000,000,001 (Math.random)
*                      60,000 (timestamp)
-----------------------------
6,000,000,000,000,000,060,000

그건 6,000,000,000,000,000,060,000 변의 다이입니다.또는, 이 숫자를 인간이 소화할 수 있도록 하기 위해, 이것은 대략 다음과 같은 숫자입니다.

input                                            outputs
------------------------------------------------------------------------------
( 1×) 6,000,000,000,000,000,060,000-sided die    6,000,000,000,000,000,060,000
(28×) 6-sided die                                6,140,942,214,464,815,497,21
(72×) 2-sided coins                              4,722,366,482,869,645,213,696

꽤 괜찮은 것 같네요, 그렇죠? 그럼...

SHA1은 20바이트 값을 생성하며 256^20의 결과를 얻을 수 있습니다.따라서 SHA1을 최대한 활용하지 않고 있습니다.그럼 우리는 얼마나 사용하나요?

node> 6000000000000000060000 / Math.pow(256,20) * 100

1밀리초 타임스탬프와 Math.random은 SHA1의 160비트 잠재량의 4.11e-27%만을 사용합니다.

generator               sha1 potential used
-----------------------------------------------------------------------------
crypto.randomBytes(20)  100%
Date() + Math.random()    0.00000000000000000000000000411%
6-sided die               0.000000000000000000000000000000000000000000000411%
A coin                    0.000000000000000000000000000000000000000000000137%

세상에!요.저 영점들 좀 봐요.요가 요?crypto.randomBytes(20)? 243,583,606,221,817,150,598,111,409배 향상


에 대한 +1 0와 0.

에 이.+1합니다.Math.random답례하다, 답례를 하다0그 말은 우리가 설명해야 할 독특한 결과가 하나 더 있다는 뜻입니다.

을 바탕으로 에 에0올라올 겁니다.다.random_zero.js, 자료를 좀 얻기 위해 만들었습니다.

#!/usr/bin/env node
var count = 0;
while (Math.random() !== 0) count++;
console.log(count);

그런 다음 4개의 스레드(4-core processor 있음)로 실행하여 출력을 파일에 추가했습니다.

$ yes | xargs -n 1 -P 4 node random_zero.js >> zeroes.txt

A 0그렇게 어렵지는 않습니다.100개의 값이 기록된 후, 평균은

3분의 1, 164, 854,823개의 무작위는 0입니다.

이요 의한 분포와 더 많은 가 필요할 입니다. 가 v8 의입니다.Math.random.

여기를 확인해 보십시오.node.js Crypto를 사용하여 HMAC-SHA1 해시를 생성하는 방법은 무엇입니까?해시 고유성을 보장하기 위해 현재 타임스탬프의 해시 + 랜덤 숫자를 만듭니다.

var current_date = (new Date()).valueOf().toString();
var random = Math.random().toString();
crypto.createHash('sha1').update(current_date + random).digest('hex');

브라우저에서도 해보세요!

편집: 이것은 제 이전 답변의 흐름에 잘 맞지 않았습니다.브라우저에서 이 작업을 수행할 수 있는 사용자를 위한 두 번째 답변으로 남겨둡니다.

당신이 원한다면 현대 브라우저에서 이 클라이언트 쪽을 할 수 있습니다.

// str byteToHex(uint8 byte)
//   converts a single byte to a hex string 
function byteToHex(byte) {
  return ('0' + byte.toString(16)).slice(-2);
}

// str generateId(int len);
//   len - must be an even number (default: 40)
function generateId(len = 40) {
  var arr = new Uint8Array(len / 2);
  window.crypto.getRandomValues(arr);
  return Array.from(arr, byteToHex).join("");
}

console.log(generateId())
// "1e6ef8d5c851a3b5c5ad78f96dd086e4a77da800"

console.log(generateId(20))
// "d2180620d8f781178840"

브라우저 요구사항

Browser    Minimum Version
--------------------------
Chrome     11.0
Firefox    21.0
IE         11.0
Opera      15.0
Safari     5.1

고유 식별자를 얻고 싶다면 UUID(Universally Unique Identifier) / GUID(Global Unique Identifier)를 사용해야 합니다.

해시는 어떤 크기의 입력을 위해서도 결정론적이고 고유하며 고정된 길이여야 합니다.따라서 해시 함수를 몇 번 실행해도 동일한 입력을 사용하면 출력은 동일합니다.

UUID는 고유하고 임의로 생성됩니다!'uuid'라는 패키지가 있습니다. npm을 통해 설치할 수 있습니다.

npm 설치 uuid

& 코드에서 모듈을 다음과 같이 가져옵니다.

const {v4:uuidv4} = required ('uuid')

// Method uuidv4를 호출하거나 불러오는 동안 이름을 지정하거나 저장하거나 할당합니다.메서드는 문자열 형태의 UUID를 반환합니다.

console.log(uuuidv4()); // 출력 예시 : '59594fc8-6a35-4f50-a966-4d735d8402ea'

npm 링크(필요하시면) : https://www.npmjs.com/package/uuid

으로.crypto이지만,다를 할 수 .bcrypt정말 강력하고 안전한 해시를 만들고 싶다면요.나는 그것을 비밀번호를 위해 사용합니다. 그것은 해싱, 소금 만들기, 비밀번호 비교를 위한 많은 기술들을 가지고 있습니다.

테크닉 1 (별도 함수 호출 시 솔트 및 해시 생성)

const salt = bcrypt.genSaltSync(saltRounds);
const hash = bcrypt.hashSync(myPlaintextPassword, salt);

테크닉 2 (자동 유전자 염 및 해시):

const hash = bcrypt.hashSync(myPlaintextPassword, saltRounds);

자세한 예는 여기에서 확인할 수 있습니다: https://www.npmjs.com/package/bcrypt

언급URL : https://stackoverflow.com/questions/9407892/how-to-generate-random-sha1-hash-to-use-as-id-in-node-js

반응형