티스토리 뷰

Security

[Node.js] PBKDF2 모듈을 이용한 비밀번호 보안

꿈을 위해 잠을 잊은 그대에게 2018. 7. 17. 03:40

앞서 md5, sha256을 이용한 비밀번호 보안 실습에 이어서 pbkdf2-password 모듈을 이용한 실습을 진행하겠습니다.


* PBKDF2란 무엇인가?


PBKDF2(Password-Based Key Derivation Function2)


암호 반복횟수, 암호기반 키 유도함수2..


암호화 된 키의 무차별 대입 공격에 대한 취약성을 줄이기 위해 계산 비용이 많이 소요되는 주요 파생 함수이다.


md5, sha256에 이어서 더욱 복잡하게 암호화 할 수 있는 기능을 가지고 있는 해시 함수라고 보시면 될 것 같습니다.




모듈 설치


모듈 테스트를 위한 node 실행



암호화된 해시 값 확인


function(err, pass, salt, hash)

함수의 순서대로 해당 값 확인

ex) null '111111' 'salt' 'password'


var users = [
{
username: 'swk',
password: 'hcBng2j2P7vFsJ0a0g4P5owVO+mI0Wujtd6q7yivciHvm1RJobUNc1Zj/leg/rQXBkSuFxK0iU4Y2j+wLByYtq1Qm1EWDH9hyrbiwgH7g99l8LDT4jx0eaDwP84XHaPp6mOWmzsVu+XwVocIXSzu3QdmHLqJZzPdSIlqT8su1mQ=',
salt:'G34WguBAJgbPPi6BtQ/H1l+38dRq9Vyanv/orzkqllTUctKg4cLC14sNKX4IigZ88s90b/WdNMcxIL/4qGrakg==',
displayName:'swk'
},
];


해당 변수에 암호화 된 코드 삽입


var bkfd2Password = require("pbkdf2-password");
var hasher = bkfd2Password();


모듈 선언


app.post('/auth/login', function(req, res){
var uname = req.body.username;
var pwd = req.body.password;
for(var i=0; i<users.length; i++){
var user = users[i];
if(uname === user.username) {
return hasher({password:pwd, salt:user.salt}, function(err, pass, salt, hash){
if(hash === user.password){
req.session.displayName = user.displayName;
req.session.save(function(){
res.redirect('/welcome');
})
} else {
res.send('Who are you? <a href="/auth/login">login</a>');
}
});
}
// if(uname === user.username && sha256(pwd+user.salt) === user.password){
// req.session.displayName = user.displayName;
// return req.session.save(function(){
// res.redirect('/welcome');
// });
// }
}
res.send('Who are you? <a href="/auth/login">login</a>');
});


기존의 패스워드 값과 새로운 패스워드 값을 비교하는 방식이 아닌

반환하는 해쉬 값에 의하여 콜백되는 해쉬 값과 패스워드를 비교하는 코드



비밀번호 111111, 로그인




정상 실행 확인



+ 등록 기능


app.post('/auth/register', function(req, res){
hasher({password:req.body.password}, function(err, pass, salt, hash){
var user = {
username:req.body.username,
password:hash,
salt:salt,
displayName:req.body.displayName
};
users.push(user);
req.session.displayName = req.body.displayName;
req.session.save(function(){
res.redirect('/welcome');
});
});
});



users 변수에 미리 값을 넣어두지 않아도

/auth/register로 post 전송을 보내서 새로운 user의 정보를 users에 저장할 수 있는 코드


Register 등록 클릭


등록할 정보 입력


정상 등록 확인 후 로그아웃

등록된 개인정보 로그인 확인



로그인 성공



전체코드


var express = require('express');
var session = require('express-session');
var FileStore = require('session-file-store')(session);
var bodyParser = require('body-parser');
var bkfd2Password = require("pbkdf2-password");
var hasher = bkfd2Password();

var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
secret: '1234DSFs@adf1234!@#&asd',
resave: false,
saveUninitialized: true,
store:new FileStore()
}));
app.get('/count', function(req, res){
if(req.session.count) {
req.session.count++;
} else {
req.session.count = 1;
}
res.send('count : '+req.session.count);
});
app.get('/auth/logout', function(req, res){
delete req.session.displayName;
res.redirect('/welcome');
});
app.get('/welcome', function(req, res){
if(req.session.displayName) {
res.send(`
<h1>Hello, ${req.session.displayName}</h1>
<a href="/auth/logout">logout</a>
`);
} else {
res.send(`
<h1>Welcome</h1>
<ul>
<li><a href="/auth/login">Login</a></li>
<li><a href="/auth/register">Register</a></li>
</ul>
`);
}
});
app.post('/auth/login', function(req, res){
var uname = req.body.username;
var pwd = req.body.password;
for(var i=0; i<users.length; i++){
var user = users[i];
if(uname === user.username) {
return hasher({password:pwd, salt:user.salt}, function(err, pass, salt, hash){
if(hash === user.password){
req.session.displayName = user.displayName;
req.session.save(function(){
res.redirect('/welcome');
})
} else {
res.send('Who are you? <a href="/auth/login">login</a>');
}
});
}
// if(uname === user.username && sha256(pwd+user.salt) === user.password){
// req.session.displayName = user.displayName;
// return req.session.save(function(){
// res.redirect('/welcome');
// });
// }
}
res.send('Who are you? <a href="/auth/login">login</a>');
});
app.get('/auth/login', function(req,res){
var output = `
<h1>Login</h1>
<form action="/auth/login" method="post">
<p>
<input type="text" name="username" placeholder="username">
</p>
<p>
<input type="password" name="password" placeholder="password">
</p>
<p>
<input type="submit">
</p>
</form>
`;

res.send(output);
});

var users = [
{
username: 'swk',
password: 'hcBng2j2P7vFsJ0a0g4P5owVO+mI0Wujtd6q7yivciHvm1RJobUNc1Zj/leg/rQXBkSuFxK0iU4Y2j+wLByYtq1Qm1EWDH9hyrbiwgH7g99l8LDT4jx0eaDwP84XHaPp6mOWmzsVu+XwVocIXSzu3QdmHLqJZzPdSIlqT8su1mQ=',
salt:'G34WguBAJgbPPi6BtQ/H1l+38dRq9Vyanv/orzkqllTUctKg4cLC14sNKX4IigZ88s90b/WdNMcxIL/4qGrakg==',
displayName:'swk'
},
];
app.post('/auth/register', function(req, res){
hasher({password:req.body.password}, function(err, pass, salt, hash){
var user = {
username:req.body.username,
password:hash,
salt:salt,
displayName:req.body.displayName
};
users.push(user);
req.session.displayName = req.body.displayName;
req.session.save(function(){
res.redirect('/welcome');
});
});
});
app.get('/auth/register', function(req, res){
var output = `
<h1>Register</h1>
<form action="/auth/register" method="post">
<p>
<input type="text" name="username" placeholder="username">
</p>
<p>
<input type="password" name="password" placeholder="password">
</p>
<p>
<input type="text" name="displayName" placeholder="displayName">
</p>
<p>
<input type="submit">
</p>
</form>
`;
res.send(output);
});
app.listen(3003, function () {
console.log('Connected 3003 port!!!');
});


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크