U-eat프로젝트에서 회원정보관리르 맡아 비밀번호의 암호화 처리를 할 필요성이 발생했다. 따라서 hash처리를 할 때 쓸 수 있는 라이브러리를 찾았는데 그게 bcryptjs다. 따지면 bcrypt도 있었지만, bcrypt는 C++기반의 라이브러리로 동작시 js로 변환하는 작업을 거친다고 하는데 bcryptjs는 javascript만을 위한 라이브러리라고 설명되어 이 라이브러리를 쓰게 되었다.
bcryptjs는 해시 함수 라이브러리 중 하나로, 비밀번호와 같은 중요한 데이터를 안전하게 저장하기 위해 사용된다. bcryptjs는 JavaScript로 작성된 라이브러리이며, 데이터를 암호화하여 암호화된 데이터의 재생성을 어렵게 만든다.
우리는 일반적인 사이트에서 회원가입을 진행하고 비밀번호를 잃어버렸을 때 "비밀번호 찾기"가 아닌 "비밀번호 재설정"을 하게 된다. 이는 "단방향성 암호화처리"에 의해 관리자 조차 기존의 비밀번호를 복구할 수 없다. 위의 bcryptjs또한 "단방향성 암호화처리"를 기반으로 하기 때문에 암호화된 데이터의 재생성을 어렵게 만들 수 있다.
bcryptjs는 비밀번호를 암호화하는 과정을 "해싱(hashing)"이라고 한다. 이러한 해싱처리 기능은 내부적으로 "솔트(salt)"라는 추가적인 무작위 문자열을 사용하여 비밀번호를 보호한다. 이 솔트는 암호화된 비밀번호와 함께 저장되며, 이를 통해 각 비밀번호에 대한 고유한 해싱처리 된 값을 생성한다.
bcryptjs는 기본적으로 "10 라운드(round)"의 해싱을 사용한다. 이는 해시 함수가 2의 10승(약 1000) 번 이상 실행된다는 것을 의미한다. 이로 인해 암호화 된 비밀번호를 복호화하려는 공격자가 매우 많은 시간과 노력을 필요로 하기 때문에 보안성이 높아진다.
bcryptjs는 npm을 통해서 간단하게 설치가 가능하다
npm install bcryptjs
사용할 코드에서 bcryptjs를 가져와서 비밀번호를 암호화하고 검증할 수 있다.
필자가 작성한 코드로 예시를 들면 아래는 bcryptjs로 비밀번호를 해싱처리해서 저장하는 회원가입과
해싱처리된 비밀번호를 검증하여 통화시키는 로그인의 API이다
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
//회원가입
register = async (userInfo) => {
const { email, nickname, password } =
await registerRequestPattern.validateAsync(userInfo);
const isExistUser = await this.authRepository.getUserByEmailOrNickname({
email,
nickname,
});
if (isExistUser[0]) throw new ApiError('중복된 이메일 또는 닉네임', 400);
const encryptedPassword = await bcrypt.hash(password, 10);
await this.authRepository.register({ email, nickname, encryptedPassword });
};
//로그인
userLogin = async (loginInfo) => {
const { email, password } = await loginRequestPattern.validateAsync(
loginInfo,
);
const [isExistUser] = await this.authRepository.getUserByEmail({ email });
if (!isExistUser) throw new ApiError('이메일 또는 비밀번호 불일치', 401);
const decipheredPassword = await bcrypt.compare(
password,
isExistUser.password,
);
if (decipheredPassword !== true)
throw new ApiError('이메일 또는 비밀번호 불일치', 401);
const token = await jwt.sign(
{ userId: isExistUser.userId },
JWT_SECRET_KEY,
{
expiresIn: '1h',
},
);
await loginResponsePattern.validateAsync(token);
return { token, nickname: isExistUser.nickname };
};
좀 더 간단한 예제나 자세한 사용방법을 확인하려면 bcryptjs github readme를 확인하자
bcryptjs는 다음과 같은 특징을 가진다.
bcryptjs는 솔트와 해시 함수를 사용하여 비밀번호를 안전하게 저장할 수 있기 때문에 아래와 같은 장단점을 가진다.
참고자료(출처)
12 - Bcryptjs - Cómo hacer hashing de una password. 유튜브 동영상
bcryptjs github readme
bcrypt의 작동원리와 노드에서 사용하는 방법