암호화에는 크게 세 가지 방법이 있다.
node.js에 내장되어 있는 crypto 모듈은 단방향 암호화를 이용하고 있다.
단방향 암호화의 대표 주자는 해시 기법이다. 해시기법은 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식이다.
여기서 중요한 것은 암호화 된 암호를 다시 평문으로 바꿀 수 없다(복호화 불가능). 특정 단어를 해시화하면 같은 결과를 가져온다. 그래서 DB에는 해시화된 암호를 저장하여 DB를 해킹당해도 비밀번호를 보호할 수 있다.
const crypto = require('crypto');
crypto.createHash('sha512').update('비밀번호').digest('base64'); // 'dvfV6nyLRRt3NxKSlTHOkkEGgqW2HRtfu19Ou/psUXvwlebbXCboxIPmDYOFRIpqav2eUTBFuHaZri5x+usy1g=='
crypto.createHash('sha512').update('비밀번호').digest('base64'); // 위와 같은 결과
위에 예시를 자세히 보면
하지만, 이러한 방식도 같은 알고리즘과 인코딩 방식을 사용하면 같은 비밀번호에 대해 같은 결과를 반환한다.
그래서 만약 해커가 모든 암호에 대해 어떤 결과가 나올지 데이터베이스화 해두었다면, 결과만 보고도 원래 암호를 유추해낼 수 있다. 이러한 데이터베이스를 레인보우 테이블이라고 한다.
이러한 레인보우 테이블을 사용하지 못하도록 하기위해 Salt를 사용해야한다. salt라는 특정 값을 통해서 해시화 결과를 변형할 수 있다. 비밀번호에 salt 문자열을 붙여서 그것을 수 만번 반복 해시화 하는 방식이다. salt는 랜덤 문자열을 생성해서 비밀번호와 같이 DB에 저장한다.
crypto.randomBytes(64, (err, buf) => {
crypto.pbkdf2('비밀번호', buf.toString('base64'), 100000, 64, 'sha512', (err, key) => {
console.log(key.toString('base64')); // 'dWhPkH6c4X1Y71A/DrAHhML3DyKQdEkUOIaSmYCI7xZkD5bLZhPF0dOSs2YZA/Y4B8XNfWd3DHIqR5234RtHzw=='
});
});
위의 예시를 자세히 보면,
출처: