[ 암호화 종류 ]
[ 해시 (Hash) ]
[ bcrypt ]
[ 암호화 보완법 ]
salt : 입력한 값에 salt 라는 특정 값을 붙여 변형시키는 것 (소금을 치는 것과 비슷하다고 그래서 salt 라고 부름)[ 레인보우 테이블 ]
[ crypto ]
[ crypto 검증 ]
crypto 는 단방향 알고리즘이기 때문에 복호화가 불가능salt 값을 사용하여야 하므로 데이터베이스에 salt 값도 저장해주어야 한다.[ 실습 - crypto ]
crypto 설치
$ npm i crypto
MVC - Controller
const models = require("../model");
// crypto 모듈 가져오기
const crypto = require('crypto');
exports.main = (req, res) => {
res.render("index");
}
exports.register = async (req,res) => {
// 해시 알고리즘
const createHashedPassword = (password) => {
//randomBytes(64) : 64바이트 길이로 salt를 생성한다.
const salt = crypto.randomBytes(64).toString('base64');
//pbkdf2sync(해시할 값, salt, 해시 함수 반복 횟수, 해시 값 길이, 해시 알고리즘)
const hashed = crypto.pbkdf2Sync(password, salt, 10, 64, 'sha512').toString('base64');
// 해시 값(암호화된 비밀번호)과 salt를 반환한다
return {hashed, salt};
}
// 해시 값 : hashed.hashed, salt : hashed.salt
let hashed = createHashedPassword(req.body.pw);
let hashedPassword = hashed.hashed;
let salt = hashed.salt;
// 데이터베이스에 아이디, 해시 값, salt를 삽입한다.
let obj = {
id : req.body.id,
password: hashedPassword,
salt: salt
}
let result = await models.User.create(obj);
res.render("login");
}
exports.loginPage = (req, res) => {
res.render("login");
}
exports.postLogin = async (req, res) => {
// id로 salt값을 가져온다 (아이디 중복 불가)
let salt_result = await models.User.findOne({where: {id : req.body.id}});
// 가져온 salt 값과 위에서 사용한 해시 알고리즘을 사용하여 재암호화 한다.
const verifyPassword = (password, salt) => {
const hashed = crypto.pbkdf2Sync(password, salt, 10, 64, 'sha512').toString('base64');
return hashed;
}
// 해시 값
let hashedPassword = verifyPassword(req.body.pw, salt_result.salt);
// 데이터베이스에 저장되어 있는 해당 id의 암호화된 비밀번호와 방금 얻은 해시값을 비교한다
if ( salt_result.password === hashedPassword ) {
res.send("로그인 성공");
} else {
res.send("로그인 실패");
}
}
[ 실습 - bcryptjs ]
bcryptjs 설치
$ npm i bcryptjs
MVC - Controller
const models = require("../model");
// bcrypt 모듈 가져오기
const bcrypt = require("bcryptjs");
exports.main = (req, res) => {
res.render("index");
}
exports.register = async (req,res) => {
// 암호화 알고리즘
const doBcrypt = (password) => {
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(password, salt);
return hash
}
// 해시 값
let bcrypted = doBcrypt(req.body.pw);
let obj = {
id : req.body.id,
password: bcrypted
}
let result = await models.User.create(obj);
res.render("login");
}
exports.loginPage = (req, res) => {
res.render("login");
}
exports.postLogin = async (req, res) => {
// 아이디로 검색한 사용자 정보
let result = await models.User.findOne({where: {id : req.body.id}});
// bcrypt.compare(입력된 비밀번호, 암호화 된 비밀번호)
let verify_result = await bcrypt.compare(req.body.pw, result.password);
if (verify_result) {
res.send("로그인 성공");
} else {
res.send("로그인 실패");
}
}