2017-02-21 7 views
1

해시 함수는 동일한 데이터를 입력 할 때 항상 동일한 결과를 반환한다는 것을 알고 있습니다. 하지만 libsodium (node-sodium을 통해)을 사용하고 있는데, 그런 일은 일어나지 않습니다.비밀번호 해시에 대해 내가 잘못 생각하는 부분이 있습니까?

내 스키마이 있습니다

UserSchema.pre('save', function(next) { 
    // declare my variables  
    let user = this, 
     buf = Buffer.alloc(sodium.crypto_pwhash_STRBYTES, 'ascii'), 
     passwordBuf = Buffer.from(user.password, 'ascii'), 
     saltedPassBuf, 
     hash; 
    // only hash the password if it has been modified (or is new) 
    if (!user.isModified('password')) return next(); 
    // generate a salt 
    sodium.randombytes_buf(buf, sodium.crypto_pwhash_STRBYTES, 'ascii'); 
    // add salt to the password 
    saltedPassBuf = Buffer.concat([passwordBuf, buf], 128); 
    // hash it separately multiple times 
    // note, i'm not hashing the hash, 
    // I'm hashing the original buffer to see what happens 
    // this has no application in production 
    hash = sodium.crypto_pwhash_str(saltedPassBuf, sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE); 
    hash2 = sodium.crypto_pwhash_str(saltedPassBuf, sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE); 
    hash3 = sodium.crypto_pwhash_str(saltedPassBuf, sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE, sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE); 
    // log it to see what I got -- not for production 
    console.log(hash.toString()); 
    console.log(hash2.toString()); 
    console.log(hash3.toString()); 
    // save the salt and the buffer for authentication 
    user.salt = buf; 
    user.password = hash; 
    next(); 
}); 

나는 그 코드와 함께 기록 세 가지 다른 문자열을 얻을. 예 :

$argon2i$v=19$m=32768,t=4,p=1$ayPVQ1X+xNhWmD9S5AUuaw$1mWusk59AebhzOHhl+j5JpvmRI27Pq57XG5zcAB5R4U 
$argon2i$v=19$m=32768,t=4,p=1$PjTYKpfhh1bZh+MV84Y9kA$9+U33nf6efuugsrz15cEKDa5+rAHgYVA5Kqo4F1G3DE 
$argon2i$v=19$m=32768,t=4,p=1$Ii8AErmAFc0na9Yi2OgCkw$ySU80Fv9OiOmeT9EV/BWon1Jjck2Lx23nOeCk0wkMPU 

지금 그 각각의 첫 번째 부분은 제출 된 암호 부분은 같은 (이 해시되고있는 버퍼의 첫 번째 부분이기 때문에)을 나를 물건 만들기, 동일합니다. 어쩌면 이해할 수없는 버퍼 일 수도 있습니다.

그러나 buf이 정적 인 경우 나머지는 왜 saltedPassBuff으로 변경됩니까?

편집 : 내가 실수로 질문 이름이 암시로

답변

1

pwhash 함수 (문서가 최소 임)는 crypto_pwhash_str_verify을 사용하여 나중에 비교하기 위해 결과에 포함 된 자체 소금을 추가 할 가능성이 큽니다.

"CPU 집중"측면도있을 수 있습니다. 소금에 해시 함수를 사용하면 보안을 향상시키는 데별로 도움이되지 않습니다. 반복과 같이 CPU를 많이 사용하는 구성 요소를 추가해야합니다.

요점은 공격자가 무차별 암호로 많은 시간을 소비하도록하는 것입니다.

+0

이 사실입니다. 또한 .pre() 함수에서 코드 양을 반으로 줄입니다. 나는 소금이 어떻게 첨가되는지를 libsodium에서 추적하는 방법에 대해서는 언급하지 않을 것이라고 생각합니다. –

0

를 작성 완료 편집, 제출시 작성 완료하지 않았다면, 출력이 소금에 절인된다. 즉, 임의의 문자열이 해싱 전 암호에 추가되고 출력 값에 별도로 포함됩니다.

이 목적은 dictionary attacks을 (패)하는 것입니다. 해싱 전에 각 암호에 임의의 문자열을 추가하면 동일한 암호가 다르게 해시되어 공격자가 모든 암호를 개별적으로 해독해야합니다.

+0

나는 그것이 내가 묻는 것을 대답하지 않는다고 생각한다. 랜덤 데이터를'randombytes_buf()'함수를 통해 추가하려고하는데, 한 번 발생하고, 해싱 함수가 실행될 때마다 동일한 데이터 세트를 해싱합니다. 'crypto_pwhash_str()'가 실제의 해시를 실행하기 전에 랜덤 바이트를 추가하는 것을 말하는 것이 아니라면 말입니다. 그럴까요? 그렇다면 어떻게 인증합니까? –

+0

@Nick Johnson 또한이 소금은 두 개의 암호가 동일한 값으로 해시되지 않으므로 두 명의 사용자가 동일한 암호를 가지고 있다고 보증합니다. – zaph

+0

@TheE 예, 'crypto_pwhash_str'은 [the docs] (https://download.libsodium.org/doc/password_hashing/the_argon2i_function.html)에 따라 소금을 추가합니다. 직접 추가 할 필요는 없습니다. 그것은 완벽한 암호 해싱 솔루션을 의도 한 것입니다. –