20212009 TIL crypto 모듈을 사용한 암호화
crypto 모듈을 사용한 데이터베이스 비밀번호 암호화
회원가입 API 코드
const { user } = require('../../models');
const crypto = require('crypto');
require('dotenv').config();
module.exports = {
post: (req, res) => {
// TODO : 회원가입 로직 및 유저 생성 로직 작성
const { email, name, password, nickname, mobile } = req.body;
const encrypted = crypto
.pbkdf2Sync(password, process.env.DATABASE_SALT, 100000, 64, 'sha512')
.toString('base64');
user
.findOrCreate({
where: {
email: email,
},
defaults: {
name: name,
password: encrypted,
nickname: nickname,
mobile: mobile,
},
})
.then(async ([user, created]) => {
if (!created) {
return res.status(409).send('email already exists');
}
res.status(201).send('created successfully');
})
.catch(err => {
res.status(500).send('err');
});
},
};
node.js 의 crypto 모듈을 사용하여 비밀번호 만을 암호화하여 유저 데이터 베이스에 저장하는 로직으로
단방향 암호화 이기 때문에 복호화가 불가능하다.
제로초: pbkdf2라는 메소드를 사용하는데요. 단방향 암호화할 때 가장 선호하는 방식 중 하나입니다.
pbkdf2에는 인자가 5개나 들어가는데요. 비밀번호, salt, 반복 횟수, 비밀번호 길이, 해시 알고리즘 순입니다. 역시 key가 버퍼 형태로 리턴해주기 때문에 base64 방식으로 문자열로 만들어서 저장해야 합니다. 반복 횟수는 해시 함수를 몇 번 반복하느냐를 나타냅니다. 10만번으로 정해주었는데요. 너무 많다고 생각하실지도 모르는데 이렇게 해도 1초가 안 걸립니다. 숫자는 1초 정도 걸릴 때까지 높여주시면 됩니다. 이 숫자가 높을 수록 슈퍼컴퓨터를 써도 레인보우 테이블을 만들기 힘들어집니다. 그리고 숫자도 10만처럼 깔끔한 숫자 말고, 108236 이런 불규칙적인 숫자를 사용하세요. 비밀번호 길이는 적당한 길이로 정해주면 됩니다.
확인해야할 부분
salt 값을 데이터 베이스에 저장하여 salt 버전 관리를 해야하는 것인지 추가적인 리서치가 필요.
컨셉: salt 버전 테이블을 미리 작성해두고, 유저가 회원가입을 할 때 해당 버전의 salt 값을 불러와 비밀번호를 암호화하고 이를 유저 테이블에 저장하는 방식이다. 의문점은, 만약 salt 테이블이 해킹 당하면 회원 정보도 탈취 당하지 않을까..?
현재는 .env 파일에 salt 값을 저장해 놓았다.
Node.js 공식 홈페이지
비동기적으로 암호화된 비밀번호를 담아오는 방법
참고 출처: www.zerocho.com/category/NodeJS/post/593a487c2ed1da0018cff95d