자료구조 Hash에서 정리했듯이 crypto를 활용하여 비밀번호를 암호화 하는 방식에 대해서 왜 사용을 하였는지에 초점을 두고 정리를 하고자합니다.
솔트(Salt)란?
암호학에서 솔트는 데이터, 비밀번호, 통과암호를 해시 처리하는 단방향 함수의 추가 입력으로 사용되는 랜덤 데이터입니다.
솔트(Salt)는 왜 사용한 것인가요?
예를 들어, 'jeong-park' 이라는 스트링을 sha512로 해시 해보겠습니다.
"2C1E444BE95BCB0236B7C82FDA667EC441B7A7E087898EA3299512675FADB1D65106905CEF0F757CB0D96A1AB82F97B83D3C64A8F30052893E6A8EC46D5935AA"
위처럼 나옵니다. 제가 아닌 다른 사람들이 'jeong-park'이라는 스트링을 입력하여 sha512로 해시하면 똑같이 나옵니다.
항상 똑같은 결과값을 반환한다면?
해시 함수를 사용하여 변환 가능한 모든 해시 값을 저장시켜 놓고 저장시켜 놓으면 원래의 비밀번호를 추출(레인보우 테이블)해낼 수 있지 않을까요?
이러한 문제 때문에 Salt을 사용하며, 또한 Key Stretching 이라는 친구를 사용합니다.
* Key Stretching은 해시된 값을 또 다시 해시 함수의 입력 값으로 넣어서 해싱을 반복하는 것입니다. 이런 방식으로 무작위 대입을 통해 해시 값을 구하는 시간을 늘려서 레인보우 테이블이나 무차별 대입 공격을 어렵게 하기 위함이라고 합니다.
1. createSalt : randomBytes 메소드로 64바이트 길이의 salt를 생성합니다. new_salt는 버퍼형식으로 나오기 때문에 toString("base64")을 사용하여 리턴해줍니다.
2. createHashedPassword : pbkdf2(유저가 입력한 비밀번호, 만들어준 솔트값, 키스트래칭, 비밀번호의 길이, 해시함수) 입니다.
(유저가 입력한 비밀번호 + 솔트 값) => Hash 값을 * Key Stretching 만큼 반복 하여 = HashedPassword를 만들어 줍니다.
const crypto = require('crypto');
const util = require('util');
const pbkdf2Promise = util.promisify(crypto.pbkdf2);
const randomBytesPromise = util.promisify(crypto.randomBytes);
module.exports = {
/**
* Salt Create
* @returns String
*/
createSalt: async () => {
const new_salt = await randomBytesPromise(64);
return new_salt.toString("base64");
},
/**
* Create HashedPassword
* @param {String} password
* @returns String, String
*/
createHashedPassword: async (password, currnet_salt) => {
const salt = currnet_salt;
const key = await pbkdf2Promise(password, salt, Number(process.env.KEY_STRETCHING), 64, "sha512");
const hashedPassword = key.toString("base64");
return { hashedPassword, salt };
},
/**
* verifyPassword
* @param {String} password
* @param {String} userSalt
* @param {String} userPassword
* @returns boolean
*/
verifyPassword: async (password, userSalt, userPassword) => {
const key = await pbkdf2Promise(password, userSalt, Number(process.env.KEY_STRETCHING), 64, 'sha512');
const hashedPassword = key.toString('base64');
if (hashedPassword === userPassword) return true;
return false;
}
}
참고 사이트 : https://ko.wikipedia.org/wiki/%EC%86%94%ED%8A%B8_(%EC%95%94%ED%98%B8%ED%95%99)
'개발일지 > NODE' 카테고리의 다른 글
[Node.js] generic-pool (0) | 2024.02.11 |
---|---|
Node.js에서 'devDependencies' 와 'dependencies' 의 차이 (1) | 2023.12.20 |
[Node.js] 에러핸들러 만들어보기 (0) | 2023.04.21 |
[Node.js] JWT 에러 핸들링 (0) | 2023.04.19 |