암호화가 필요한 이유?
만약 암호화를 하지 않고 사용자의 입력을 그대로(이를 평문이라고 한다) 저장하게 되면,
데이터베이스가 유출되었을 때 사용자의 비밀번호가 제3자에게 노출되게 되며, 이는 심각한 피해를 가져올 수 있다.
따라서 이러한 피해를 방지하기 위하여, 사용자의 비밀번호는 암호화를 거쳐 저장되어야 한다.
이번 포스팅에서는 그 중에서도 강력한 해시 알고리즘으로 유명한 bcrypt
를 이용해본다.
암호화된 패스워드의 생성
우선 bcrypt 모듈을 설치한다.
npm i bcrypt
프로젝트에 적용하기 위해, 암호화된 비밀번호를 생성하는 간단한 함수를 구현해보았다.
import { genSalt, hash } from 'bcrypt';
const saltRound = 10;
const createHashPassword = async (password: string): Promise<string> => {
const salt = await genSalt(saltRound);
const hashPassword = await hash(password, salt);
return hashPassword;
};
1. salt
bcrypt는 salt
라는 string value를 이용하여 같은 비밀번호일지라도 매 순간마다 다른 암호문을 생성한다.
2. saltRound
또한, bcrypt는 saltRound
라는 값을 설정하여 hash 값을 계산하는 데에 걸리는 시간을 지연시킴으로써, 브루트포싱(가능한 모든 경우를 시도하는 알고리즘)으로 비밀번호를 유추하기 어렵게 만든다.
(출처: 스택오버플로우(https://stackoverflow.com/questions/46693430/what-are-salt-rounds-and-how-are-salts-stored-in-bcrypt))
입력된 비밀번호와의 비교
bcrypt는 복호화를 제공하지 않기 때문에, 비밀번호의 유효성을 검증하기 위해 우리는
사용자로부터 입력받은 비밀번호를 암호화하여
기존에 암호화된 비밀번호와 salt를 제외한 부분을 비교해야 한다.
물론 이것 역시 bcrypt 모듈에서 내장 함수로 제공한다.
import { compare } from 'bcrypt';
const compareResult = await compare(password, user.password);
첫 번째 파라미터가 입력받은 평문 비밀번호이며,
두 번째 파라미터가 데이터베이스에 저장된 암호화된 비밀번호이다.
compare 함수는 비밀번호가 유효하다면 true, 유효하지 않다면 false를 반환한다.
이때, compare 함수가 Promise을 반환함에 주의해야 한다.