비밀번호 암호화 (crypto,Bcrypt)
강의를 듣기 전에 비밀번호 암호화로 유명한 Bcrypt
라이브러리를 사용하여 회원가입한 유저의 비밀번호를 암호화하는 로직을 작성했었다. 오늘 부트캠프 강의를 들으며 강사님이 nodejs의 내장 모듈인 crypto
를 사용해서 암호화하는 내용을 보고 차이점이 궁금해 추가로 학습하였다.
📕비밀번호 암호화 방식
#단방향 암호화
평문을 암호화시킬 수 있음
단, 암호화를 평문으로 변환은 할 수 없음
#양방향 암호화
평문을 암호화 시킬 수 있으며, 암호화를 평문으로 변환할 수 있음
비밀번호는 본인만이 알고 있어야하기때문에, 단방향 암호화 방식을 사용한다.
📕Crypto
Node.js의 내장 모듈, 여러 해시 함수를 사용하여 암호화 기능을 제공한다.
단순 Hash를 통한 암호화는 보안에 취약하기 때문에,Salt값과 다중 Hash함수를 통해 보안성을 강화시켜준다.
pbkdf2
crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)
- password: 해시되기를 원하는 비밀번호
- salt : 무작위로 데이터를 혼합시키는 값
- iterations : 알고리즘이 반복되는 횟수
- keylen : 생성되는 키의 길이
- digest : 사용할 해시 함수 (‘sha256’, ‘sha512’)
- callback : 계산이 완료되면 호출할 비동기 콜백 함수
#암호화하기
1
2
3
4
5
6
7
8
9
10
11
12
const crypto = require("crypto");
const password = "mySecretPassword";
const salt = crypto.randomBytes(16).toString("hex"); // 무작위 솔트 생성
const iterations = 100000; // 적절한 반복 횟수 선택
const keylen = 64; // 생성되는 키의 길이
const digest = "sha512"; // 해시 함수 선택
crypto.pbkdf2(password, salt, iterations, keylen, digest, (err, derivedKey) => {
if (err) throw err;
console.log("Derived Key:", derivedKey.toString("hex"));
});
#검증하기
단방향 암호화이기때문에 복호화를 할 수 없다. 따라 유저가 입력한 password도 암호화해서 암호화되어있는 비밀번호와 비교해야한다.
1
2
3
4
5
6
7
8
9
const password = "유저가 새롭게 입력한 비밀번호";
const userPassword = "데이터베이스에 저장되어있는 비밀번호";
const verifyPassword = (password, userSalt, userPassword) => {
const key = pbkdf2Promise(password, userSalt, 99999, 64, "sha512");
const hashedPassword = key.toString("base64");
if (hashedPassword === userPassword) return true;
return false;
};
※ 주의
회원가입 시 암호화된 비밀번호와 salt 값을 같이 저장해야함
📕Bcrypt
암호를 해시하는데 가장 많이 사용하는 라이브러리 중 하나이다. 해싱에 느리고 비용이 많이 드는 Blowfish 알고리즘으로 구현되어있다.
동기적 방식, 비동기적 방식 모두 사용할 수 있지만 문서에서는 비동기적 방식을 사용하는 것을 권장한다. (CPU를 많이 사용하기 때문에)
#설치
1
npm install bcrypt
#암호화하기
비동기: hash(data, salt, cb);
동기: hashSync(data, salt);
- data : 암호화할 데이터
- salt : 비밀번호를 해시하는 데 사용되는 솔트
- cb : 데이터가 암호화되면 실행되는 콜백 (선택)
1
2
3
4
const bcrypt = require("bcrypt");
bcrypt.hash(password, 10);
bcrypt.hashSync(password, 10);
#비밀번호 비교하기
비동기: compare(data, encrypted, cb)
동기: compareSync(data, encrypted)
- data : 비교할 데이터
- encrypted : 비교할 데이터
- cb : 데이터가 비교되면 실행되는 콜백 (선택)
1
2
3
4
const bcrypt = require("bcrypt");
bcrypt.compare(password, loginUser.password);
bcrypt.compareSync(password, loginUser.password);
참고 사이트