웹 서비스를 운영하면 사용자 정보를 안전하게 저장하고 관리해야 한다.
이를 위해 암호화하거나 해싱하는 등의 작업이 필요한데, Node.js 환경에서는 bcrypt, Scrypt, crypto 등의 모듈을 통해 이 작업을 수행할 수 있다.
이 중, crypto 모듈을 사용해 사용자의 정보(비밀번호)를 암호화하는 방법에 대해 알아본다.
Crypto 모듈 설치
npm install crypto
위 명령어를 통해 crypto 모듈을 설치할 수 있다. package.json의 dependencies에도 자동으로 crypto가 추가된다.
Typescript 환경에서 작업하는 경우에도 특별히 다른 모듈 설치 없이 사용할 수 있다.
Crypto로 비밀번호 암호화하기
비밀번호 암호화는 위 그림의 순서대로 진행되는데, 그림에 설명을 덧붙여보자면
- 사용자의 비밀번호를 받아온다.
- 무작위로 생성된 Salt 값과 사용자 비밀번호를 합쳐 암호화, 해싱을 진행한다.
- 암호화 처리된 비밀번호를 저장소에 보관한다.
※ Salt란?
비밀번호 해싱에 사용하는 무작위 문자열을 Salt라 한다.
Salt를 사용해 해싱하면 , 문자열 사이사이에 무작위 값을 추가하여 암호화하기 때문에, 같은 암호여도 서로 다른 문자열을 생성해 이를 유추할 수 없고, 암호를 안전하게 보관할 수 있다.
위 과정을 코드로 구현하면 아래와 같다.
이 코드에서는 암호화와 해싱에 PBKDF2, SHA512 알고리즘을 사용했지만,
반드시 이 2가지로 작업을 해야 하는 것은 아니고, 여러 다른 암호화 알고리즘 중 적절한 알고리즘을 선택해 적용하면 된다.
import crypto, { randomBytes } from 'crypto';
const userPassword: string = '사용자의 비밀번호';
// Salt값 생성
const salt: string = crypto.randomBytes(16).toString('hex');
// 비밀번호 해싱
function hashPassword(password: string, salt: string): string {
const hash = crypto.pbkdf2Sync(password, salt, 10000, 64, 'SHA512').toString('hex');
return hash;
}
// 비밀번호를 해싱하여 저장
const hashedPassword: string = hashPassword(userPassword, salt);
해싱은 단방향이기 때문에, 위 작업으로 해싱된 비밀번호는 어떤 방법으로도 평문(암호화 전 상태)으로 되돌릴 수 없다.
※ 암호화 함수의 매개변수
pbkdf2Promise('password', 'salt', 'iterations', 'keyLength', 'digest');
iterations : 반복할 횟수(정수값)
keyLength : 해싱으로 생성할 결과값의 길이(정수값)
digest : 해싱에 사용할 알고리즘(SHA-512, SHA-256 등)
그렇다면 사용자가 로그인을 요청할 때 입력한 비밀번호가 저장소에 저장된 비밀번호와 일치하는지 어떻게 확인할까?
// DB에서 로그인을 요청한 사용자의 usersalt와 암호화된 userPassword 값을 가져온다.
const verifyPassword = async (inputPassword: string, userSalt: string, userPassword: string) => {
const key = await pbkdf2Promise(inputPassword, userSalt, 10000, 64, "SHA512");
const hashedPassword = key.toString("base64");
if (hashedPassword === userPassword) {
return true;
} else {
return false;
}
}
const isPasswordValid = await util.verifyPassword(password, salt, hashedPassword);
if (isPasswordValid) {
// 로그인 성공시 작업
} else {
// 로그인 실패시 작업
}
입력한 암호를 (사용자의 회원가입 때 사용했던) salt 값으로 암호화 & 해싱을 했을 때, DB에 저장된 암호와 일치하는지 비교하는 방식으로 사용자의 로그인을 처리한다.
반복 횟수, 사용 알고리즘 등은 회원가입 로직 등을 통해 다시 확인할 수 있지만, salt 값은 항상 무작위로 생성되므로 분실할 경우 재생성할 수 없다. 따라서 정상적으로 사용자의 로그인 요청을 처리하려면, 회원가입 시 생성된 사용자별 Salt 값과 암호화된 비밀번호를 DB 등 저장소에 적절히 관리해야 한다.
'Framework > Node.js' 카테고리의 다른 글
[Node.js] Node.js 서버에서 AWS S3 이미지 가져오기 (0) | 2023.09.20 |
---|---|
[Node.js] env로 환경변수 관리하기 (0) | 2023.09.13 |
[Node.js] 간단한 로그인 기능 구현하기 (0) | 2023.09.12 |
[Node.js] Cookie-Parser로 쿠키 구현하기 (0) | 2023.09.11 |