Post

비밀번호 암호화 (crypto,Bcrypt)

강의를 듣기 전에 비밀번호 암호화로 유명한 Bcrypt 라이브러리를 사용하여 회원가입한 유저의 비밀번호를 암호화하는 로직을 작성했었다. 오늘 부트캠프 강의를 들으며 강사님이 nodejs의 내장 모듈인 crypto를 사용해서 암호화하는 내용을 보고 차이점이 궁금해 추가로 학습하였다.

📕비밀번호 암호화 방식

#단방향 암호화

평문을 암호화시킬 수 있음
단, 암호화를 평문으로 변환은 할 수 없음

#양방향 암호화

평문을 암호화 시킬 수 있으며, 암호화를 평문으로 변환할 수 있음

비밀번호는 본인만이 알고 있어야하기때문에, 단방향 암호화 방식을 사용한다.

📕Crypto

공식 문서 - node.js v.20.xx.x

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);

참고 사이트

This post is licensed under CC BY 4.0 by the author.