비밀번호 암호화 (pbkdf2, salt, hash, 사용)
2021. 11. 18. 17:10ㆍ프로그래밍/개인프로젝트
암호화
사용자의 정보를 받을 때 비밀번호를 직접 받으면 보안에 굉장히 취약하다는 문제가 있다
그래서 입력받은 비밀번호를 해쉬값으로 변경해서 서버에 저장해야한다
해쉬? : 입력값을 일정한 로직에 따라 사람이 알 수 없는 문자로 변환해줌
내생각 :
hash를 사전에 검색하면 나오는 정의
1.'#'이라는 기호
2.'고기와 감자를 잘게 다져 섞어 요리하여 따뜻하게 차려 낸 것' 이라는 요리법
해시함수에 대한 정의
1.'하나의 주어진 출력에 대하여 이 출력으로 사상시키는 하나의 입력을 찾는 것이 계산적으로 불가능하고, 하나의 주어진 입력에
대하여 같은 출력으로 사상시키는 또 다른 입력을 찾는 것이 계산적으로 불가능하...'
즉, 요리에 빗대서 쉽게 생각해보면 고기와 감자를 잘게다져서 섞으면 어떤재료들이 어떤 형태로 들어갔는지
사람은 알 수 없게 되는것처럼 입력값을 사람이 알 수 없는 문자들로 변환해주는 작업이라고 할 수 있다
md5를 사용하는 방법 (사용금지, 단순 공부용)
1. 모듈설치
npm istall md5
2. server에 md5 로드
let md5 = require('md5')
사용자가 입력하는 값을 md5()로 묶어주고 서버와 대조해서 맞으면 로그인
사용예제 :
md5('입력값')을 출력해보면 단어에 따라 암호화된 문자를 출력해준다
md5는 단방향 이다 (입력값→해쉬값은 가능, 해쉬값으로 입력값을 알아내는것은 불가능'
사용상의 문제 :
하지만 암호화된 해쉬값을 입력값으로 변환해주는 프로그램을 사용하면 중요 정보가 노출될 수 있으므로 단독으로 사용하면 안된다
그리고 보안이 뚫렸으므로 md5는 암호화로서의 가치가 없어졌다고 할 수 있다
해쉬값변환을 통한 정보노출에 대한 해결책 salt
랜덤생성되는 암호화 키값인 salt를 사용자가 입력한 비밀번호에 더해줘서 암호화된 해쉬값을 만들면
해쉬값 변환 프로그램을 통해 알 수가 없다
서버에 비밀번호+salt를 넣어두고 입력값으로 md5(pwd+salt)를 하면 해결
salt값을 생성해주는 pbkdf2를 사용하도록 해보자
pbkdf2 (Password-Based Key Derivation Function 2)
pbkdf2는 키 스트레칭 기법 (중첩암호화기법)을 사용하기 위해 만들어진 함수이다
사용방법
1. 모듈설치
npm install pbkdf2-password
2. server.js에 코드작성
let bkfd2Password = require('pbkdf2-password')
let hasher = bkfd2Password();
hasher({password:'비밀번호'}, function(err, pass, salt, hash){
console.log(err, pass, salt, hash);
//콘솔로그로 찍으면 err = undefined, pass:입력한비밀번호값, salt: 랜덤생성, hash: 입력비밀번호+salt값에 대한 해쉬값 을 출력해준다
})
내 프로그램에 적용?
회원가입부분과 로그인 부분에 코드를 추가하였다
회원가입
app.post('/signupResult',function(req, res){
hasher({password: req.body.password}, function(err, pass, salt, hash){
// console.log(err, pass, salt, hash);
// err = undefined, pass:입력한비밀번호값, salt: 랜덤번호생성, hash: 입력비밀번호+salt값에 대한 해쉬값 을 출력해준다
db.collection('users').insertOne({ id : req.body.loginId, hashPassword : hash, saltPassword : salt, email : req.body.email, number : req.body.number, gender : req.body.gender,birthday : req.body.birthday, }, function(err, result){
console.log('db save')
})
res.send("<script>alert('회원가입하셨습니다.');location.href='/login';</script>");
})
})
로그인
app.get('/login',function(req, res){
let fmsg = req.flash(); // 로그인 실패시 출려되는 플래시메세지
// console.log(fmsg); // 아이디가 없는지 , 비밀번호가 틀렸는지 검사해서 작성해놓은 message를 출력해준다
let feedback= '';
if(fmsg.error){
feedback = fmsg.error[0]
}
res.render('login.ejs', {loginFeedback : feedback})
});
//passport라이브러리 사용
app.post('/login', passport.authenticate('local', { // 로컬방식으로 인증
failureRedirect : '/fail' ,
failureFlash : true //실패시 /fail페이지로 이동시키기
}), function(req, res){
res.redirect('/') // 성공시 redirect해서 홈페이지로 보내주기
});
app.get('/fail', function(req, res){ // /fail로 접속시 처리할 코드 (alert창을 띄우고 로그인으로 리다이렉트)
res.redirect('/login')
})
//new LocalStrategy인증방식
//LocalStrategy( { 설정 }, function(){ 아이디비번 검사하는 코드 } )
passport.use(new LocalStrategy({
usernameField: 'loginId', //사용자가 제출한 id가 어디 적혔는지(input의 name 속성값)
passwordField: 'loginPassword', //사용자가 제출한 pw가 어디 적혔는지(input의 name 속성값)
session: true, //로그인 후 세션을 저장할지 ?
passReqToCallback: false, //사용자가 입력한 id,pw외에 다른정보도 검증해보고 싶으면
}, function (inputId, inputPw, done) {
// console.log(입력한아이디, 입력한비번); //-> 사용자가 입력한 id/pw가 콘솔로그로 출력됨
db.collection('users').findOne({ id: inputId }, function (err, user) {
//입력한 id에 대한 서버 정보를 결과에 담아옴
if (err) return done(err) //에러처리문법
//done은 3개의 파라미터를 가질수 있음, 1: 서버에러, 2: 성공시 사용자db, 3:에러메시지
if (!user) {
console.log('아이디가없어요')
return done(null, false, { message: 'incorrect id' })
}
if(user){
console.log('유저있어요')
hasher({password:inputPw, salt: user.saltPassword}, function(err, pass, salt, hash){ //입력비밀번호와 유저의 salt를 가져와서 hash로 만들고
// console.log(err, pass, salt, hash);
// err = undefined, pass:입력한비밀번호값, salt: 랜덤번호생성, hash: 입력비밀번호+salt값에 대한 해쉬값 을 출력해준다
// 입력비밀번호와 유저의 salt를 가져와서 만든 hash와 서버의 해쉬값과 일치하다면 로그인성공
if (hash == user.hashPassword) {
return done(null, user)
} else {
console.log('비밀번호가 틀렸어요');
return done(null, false, { message: 'incorrect password' })
}
})
}
})
}));
출처 : 생활코딩 암호화 강좌 + 프로젝트 적용을 위한 개인 공부
'프로그래밍 > 개인프로젝트' 카테고리의 다른 글
POMOTODO(11) (0) | 2021.12.28 |
---|---|
POMOTODO(10) 중간정리 (0) | 2021.12.14 |
POMOTODO(9) - 서버환경 구축, 작업코드 서버환경에 생성 +@ (0) | 2021.11.02 |
POMOTODO(8) - 메인페이지 거의 구현완료, 서버공부 (0) | 2021.11.01 |
POMOTODO(7) - 개발진행중,2주간의 결과물 (0) | 2021.10.25 |