이전까지 단방향 암호화와 양방향 암호화(대칭키, 비대칭키) 그리고 단방향 암호화의 단점을 보완하기 위해 솔팅과 키 스트레칭 기법에 대해 알아보았고 실제로 Node.js에서 어떻게 비밀번호 암호화를 구현했는지에 대한 포스팅이다.
우선 다양한 암호화 방법에 대해 알아보자
이전 게시글들에서 다뤘듯이 해싱 함수의 연산속도가 빠를수록 공격자(해커)의 하드웨어를 통한 오프라인 무차별 대입 공격(Brute-force Attack)에 더 취약하다.
빠른 해시를 사용하여 암호화를 진행시 공격자는 오프라인 공격으로 초당 수십억개의 해시를 계산할 수 있다.
crypto
의 메소드이다.❗️ SHA와 Bcrypt 중 어떤것을 택해야하는가❗️
정답이 없는 것 같다. 여러가지 글을 찾아봤을때 Bcrpt를 선호하는 이유는 SHA 관련 해싱 함수들은 GPU를 이용한 공격에 취약하며 (산속도가 매우빠르기 떄문) 많은 메모리를 필요로 하지 않아 공격자에게 유리하기 때문이다.
그러나 반대로 아래 스택오버플로우 글을 보면
https://stackoverflow.com/questions/6951867/nodejs-bcrypt-vs-native-crypto "외부 모듈을 사용하면 악성 코드가 주입될 가능성이 있어 원래의 보안 목표를 무너뜨릴 수 있습니다."라고 한다. 그래서 내장 모듈인 crypto를 활용한 암호화 방식을 채택하는 것을 권하고 있다.
두 가지 방법을 모두 알고 상황에 따라 사용하는 것이 중요할 것 같다.
ISO-27001 보안 규정에 적합한 PBKDF2를 통해 비밀번호 암호화를 구현해 봤다
import util from 'util';
import crypto from 'crypto';
const randomBytesPromise = util.promisify(crypto.randomBytes);
const pbkdf2Promise = util.promisify(crypto.pbkdf2);
// 솔트 생성
const createSalt = async () => {
const buf = await randomBytesPromise(64);
return buf.toString("base64");
};
// pbkdf2를 활용하여 해싱
const createHashedPassword = async (password) => {
const salt = await createSalt();
const key = await pbkdf2Promise(password, salt, 104906, 64, "sha512");
const hashedPassword = key.toString("base64");
return { hashedPassword, salt };
};
첫 번째 함수를 통해서 솔트를 생성하고 두 번째 함수에서 SHA512 해싱 알고리즘을 통해 위에서 생성한 솔트와 함께 104906번 키 스트레칭을 하여 암호화를 했다.
그렇게 해서 위에서 생성된 해싱 함수 출력값(Digest)과 솔트를 데이터베이스에 저장해둔다.
//비밀번호 검증
const verifyPassword = async (password, userSalt, userPassword) => {
const key = await pbkdf2Promise(password, userSalt, 104906, 64, "sha512");
const hashedPassword = key.toString("base64");
if (hashedPassword === userPassword) return true;
return false;
};
실제로 비밀번호를 검증할때는 로그인 요청이 들어왔을때 입력값을 데이터베이스에서 해당 유저의 솔트 값을 들고와서 똑같은 방식으로 입력값을 해싱해서 데이터베이스에 저장되어있던 암호화된 비밀번호와 비교해서 Authorization을 진행한다.
실제로 개발 중인 서비스에 적용해보지는 못했지만 보안이 강력한 만큼 높은 수준의 보안을 필요로하는 경우에 한번 사용해보겠다.
https://inpa.tistory.com/372
https://inpa.tistory.com/entry/NODE-%F0%9F%93%9A-bcrypt-%EB%AA%A8%EB%93%88-%EC%9B%90%EB%A6%AC-%EC%82%AC%EC%9A%A9%EB%B2%95#sha-2secure_hash_algorithm_2
https://inpa.tistory.com/entry/NODE-%F0%9F%93%9A-crypto-%EB%AA%A8%EB%93%88-%EC%95%94%ED%98%B8%ED%99%94
https://velog.io/@yenicall/%EC%95%94%ED%98%B8%ED%99%94%EC%9D%98-%EC%A2%85%EB%A5%98%EC%99%80-Bcrypt