암호화(Encryption) : 평문 -> 암호문 변환
복호화(Decryption) : 암호문 -> 평문 변환
- 양방향 암호화
- 개인키 암호화 : 암호화 키 == 복호화 키
- Stream : 문자열 길이의 Stream을 생성해 bit단위로 암호화
- Block : 하나의 블럭 단위로 암호화
- 공개키 암호화 : 암호화 키 != 복호화 키
- 개인키 암호화 : 암호화 키 == 복호화 키
- 단방향 암호화 : 암호화는 가능 / 복호화는 불가능!
- Hash
: 어떤 입력이든 고정된 길이의 문자열로 반환하여 암호화
비밀번호 암호화에 주로 사용됨 / 양방향 암호화보다 빠름
(Hash에 사용되는 Hash알고리즘은 공개되어 있어서 보안에 취약
-> Salt를 넣거나, 여러번 Hash함수를 돌려서 강화해서 사용!)
- Hash
password를 숨기는 이유는 뭘까? db가 해킹당할까봐?
만일 db가 털렸을 때, salt와 암호화된 것을 털리면 원래 비번을 복호화할 수는 없으니 안전함.
암호화해보기 - crypto 내장함수 사용
const crypto = require("crypto"); //내장 암호화 모듈
//비밀번호 암호화
const salt = crypto.randomBytes(64).toString("base64");
const hashPassword = crypto
.pbkdf2Sync(password, salt, 10000, 64, "sha512")
.toString("base64");
randomBytes: 매개변수로 들어오는 숫자를 가지고 랜덤바이트를 만들어 준다. 64의 길이로 만들어줌
toString: 다시 string으로 만들어준다.base64방식의 문자열로. (기본적으로 문자열은 base64를 사용한다.)
pbkdf2Sync (password-Based Key Derivation Function 2): 이 매개변수로
(비밀번호, 솔트값, 반복 횟수, 출력 byte, 해시 알고리즘, callback) 순이다.
단방향 - 로직
1. 회원가입시 암호화된 비밀번호와, salt값 저장
2. 로그인 시 입력된 비밀번호를 salt값을 통해 비밀번호 암호화하여 비교
회원가입
const join = (req, res) => {
const { email, name, password } = req.body;
//비밀번호 암호화
const salt = crypto.randomBytes(64).toString("base64");
const hashPassword = crypto
.pbkdf2Sync(password, salt, 10000, 10, "sha512")
.toString("base64");
let sql = "INSERT INTO users (email,name,password,salt) VALUES (?,?,?,?)";
let values = [email, name, hashPassword, salt];
//암호화된 비밀번호와 salt값을 같이 db에 저장
conn.query(sql, values, (err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
return res.status(StatusCodes.CREATED).json(results);
});
};
사용한 모듈 - crypto (암호화), jsonwebtoken (토큰 발급)
로그인
const login = (req, res) => {
const { email, password } = req.body;
let sql = "SELECT * FROM users WHERE email = ?";
let values = [email];
conn.query(sql, values, (err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
const loginUser = results[0];
//암호화
const salt = loginUser.salt;
const hashPassword = crypto
.pbkdf2Sync(password, salt, 10000, 10, "sha512")
.toString("base64");
//해시 password 비교
if (loginUser && loginUser.password == hashPassword) {
//토큰 발급
const token = jwt.sign(
{
email: loginUser.email,
name: loginUser.name,
},
process.env.PRIVATE_KEY,
{
expiresIn: "15m",
issuer: "sungeun",
}
);
console.log(token);
res.cookie("token", token, {
httpOnly: true,
});
return res
.status(StatusCodes.OK)
.json({ message: `${loginUser.name}님 환영합니다.` });
} else {
return res.status(StatusCodes.UNAUTHORIZED).json({
message: "id 및 pw를 확인해주세요.",
});
}
});
};