스터디📖/Node.js

[nodejs] Node.Js 활용하기 - 섹션 3. 비밀번호 보안 (Security Password)

호프 2022. 2. 12. 13:34

Security Password 1, 2

우리의 application이 갖고 있는 사용자의 비밀번호가 노출된다면 아주 심각한 문제 발생!

db는 자체적인 보안시스템을 갖고 있지만, 보안상 취약점은 언제나 존재하기 때문에 암호화 필요.

 

md5 : 현재는 X

단방향 암호화 방법: 원래의 문자 -> 암호화된 문자 가능 / 반대는 불가능한 경우.

지금은 평문 비밀번호가 저장되어 있음 -> 단방향 암호화를 시켜서 저장.

 

> md5('111');

'698d51a19d8a121ce581499d7b701668'

 

사용자가 입력한 password도 암호화한 후 저장된 password와 비교.

var md5 = require('md5');

//app.post('/auth/login') 내용수정
var user = {
        username: 'hadestown',
        password: '698d51a19d8a121ce581499d7b701668',
        displayName: 'Hadestown'
    };
...

if (uname === user.username && md5(pwd) === user.password){
        req.session.displayName = user.displayName
        req.session.save(function(){
            res.redirect('/welcome');
        })
    }
...

BUT, md5 dictionary online 을 검색해보면 암호화된 정보를 원래의 문자로 변환 가능..

Security Password 3 - salt

md5의 취약점을 보완하기 위한 방법 -> salt 사용

var salt = '@#fa;lsje0zjlw;fmnv' // random한 문자열 주기.
md5('111'+salt); //의 결과값을 password 정보에 저장.

-> 사이트에서 검색해도 쉽게 찾을 수 없음. salt값이 워낙 희귀하기 때문에.

만약 password가 동일한 두 사람이 있는 경우, 한 사람의 비밀번호가 노출되었을 경우 다른 사람의 비밀번호도 다함께 털리는 문제 발생.. 그래서 사용자마다 다른 salt를 적용할 수 있음.

 

user 객체 안에 salt 속성 추가.

💣 이때 : 를 사용해야 하는데 = 을 사용해서 Invalid shorthand property initializer 가 발생했다.ㅎㅎ;;

그리고 각각의 salt 값을 더해서 md5를 돌려 나온 비밀번호 값을 저장.

👉 오늘날은 md5를 암호화로 사용하지 않음!! 대신 sha 사용

SHA-256은 현재 블록체인에서 가장 많이 채택하여 사용되고 있는 암호 방식이다. 출력 속도가 빠르다는 장점을 갖고 있다. 또한 단방향성의 성질을 띄고 있는 암호화 방법으로 복호화가 불가능하다. SHA-384, 512, SHA-3보다는 유효 보호 수준이 낮을 지는 모르지만, 현재까지 안정성 문제에서도 큰 단점이 발견되지 않았고, 속도가 빠르기 때문에 인증서, 블록체인 등 많이 사용되고있으며, SHA-2라고 하면 SHA-256이라고 말할 정도로 상용화가 잘 되어있다.

http://wiki.hash.kr/index.php/SHA256

var sha256 = require('sha256');

사용방법은 md5와 동일. 오늘날에도 많이 쓰이는 암호화 방식 중 하나인 것 같다.

Security Password 4 - pdkdf2

암호화 구현에 도움을 주는 함수.

https://www.npmjs.com/package/pbkdf2-password

사용 전에 모듈 설치는 기본...^^

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

hasher({password:'111'}, function(err, pass, salt, hash){
    console.log(err, pass, salt, hash);
});

실행될 때마다 다른 salt가 생성되기 때문에 암호화된 결과도 다름.

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>');
                }
            });
        }
};

비동기적 실행 때문에 hasher 함수 앞에 return을 붙여서 함수를 끝내준다.

Security Password 6 - register

회원가입 기능을 추가한다.

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 = user.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">
    `;
    res.send(output);
})