[Node.js] 패스워드 암호화를 위한 bcrypt 모듈

이예빈·2022년 4월 26일
0

Bcrypt란?

사용자의 패스워드와 같은 민감한 정보는 개발자 본인도 알아볼 수 없도록 암호화하여 데이터베이스에 저장해야한다.

어떻게 암호화를 할 수 있을까?

bcrypt라는 npm 모듈을 사용하여 패스워드를 해싱할 수 있다.
위키피디아에서 정의한 bcrypt는 아래와 같다.

  • bcrypt 정의

    bcrypt is a password-hashing function designed by Niels Provos and David Mazières, based on the Blowfish cipher and presented at USENIX in 1999.[1] Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

위에서 보다시피 bcrypt는 Niels Provos와 David Mazières에 의해 디자인된 password-hashing function이며 이 bcrypt는 1999년 USENIX (어딘진 모름)에서 발표된 Blowfish라는 암호를 기반으로 만들어졌다고 한다.

(이게 어떤 공격인진 잘 모르겠으나) rainbow table 어택에 대항하기 위해 salt를 추가했을 뿐 아니라 bcrypt는 적응형 function이다.(적응형 함수는 또 뭘까?)
: (어쨌든!) 시간이 지남에 따라, 반복 횟수를 늘려 속도를 늦출 수 있으므로 계산 성능이 향상되더라도 무차별적인 검색 공격에 대한 내성을 유지할 수 있다고 한다.

※ rainbow table 공격 : A rainbow table is a precomputed table for caching the output of cryptographic hash functions, usually for cracking password hashes.

-> 지금까지 알아본 정의에 의하면 bcrypt는 무차별적으로 패스워드를 때려맞추려는 공격이 들어와도 알아내기까지의 시간을 늦출 수 있어서 rainbow table 공격에 대항할 수 있는 password-hashing-function이라고 한다.

  • Description
    bcrypt function의 input으로는 password string과 숫자로된 cost, 16byte의 salt가 들어간다.
    salt는 일반적으론 랜덤값이다.
    bcrypt는 이러한 input값들을 24byte의 해쉬값으로 계산하기 위해 사용한다.

  • bcrypt function의 최종 output의 형태는 아래 형식의 string이다.
    $2<a/b/x/y>$[cost]$[22 character salt][31 character hash]

  • 예를 들어, password abc123xyz, cost 12, 그리고 랜덤한 salt를 갖는 bcrypt의 output은 아래와 같다.

$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
\__/\/ \____________________/\_____________________________/
Alg Cost      Salt                        Hash

bcrypt 모듈 설치하기

npm i bcrypt

bcrypt 사용법

위 npm i를 통해 모듈을 설치했다면 어떻게 사용하는 지 알아보자.

import bcrypt from 'bcrypt';

const saltRounds = 10;
const myPassword = 'abc123xyz';
const otherPassword = 'zcvd1255';

//CASE 1) 패스워드 해싱하여 변수에 할당한다면,
const myHashed = bcrypt.hash(myPassword, saltRounds);


//CASE 2) 패스워드 해싱하여 디비에 저장한다면,
bcrypt.hash(myPassword,saltRounds, function(err,hash) {
  // DB에 hash 저장하는 로직 작성..
});


//패스워드를 확인한다면,
/*
CASE 3) 
@myPassword : 로그인 요청시 올바른 패스워드를 넘겼다고 가정
@hash : DB에 저장된 hash값
@callback : 앞의 인자 둘을 비교했을 때의 결과를 리턴 -> 이 경우, true
*/
bcrypt.compare(myPassword, hash, function(err,result) {
  // result == true
});

/*
CASE 4) 
@myPassword : 로그인 요청시 틀린 패스워드를 넘겼다고 가정
@hash : DB에 저장된 hash값
@callback : 앞의 인자 둘을 비교했을 때의 결과를 리턴 -> 이 경우, false
*/
bcrypt.compare(otherPassword, hash, function(err, result) {
    // result == false
});

bcrypt를 사용하는 방식은 promise나 async/await을 활용해 비동기적으로 할 수도 있으니 자세한 사용법은 아래의 링크를 참고하자.

참고
https://www.npmjs.com/package/bcrypt
https://en.wikipedia.org/wiki/Bcrypt

0개의 댓글