NodeJS - crypto(단방향 암호화)

김정욱·2020년 12월 10일
1

NodeJS

목록 보기
4/22
post-thumbnail

암호화

암호화(Encryption) : 평문 -> 암호문 변환
복호화(Decryption) : 암호문 -> 평문 변환


  • 양방향 암호화
    • 개인키 암호화 : 암호화 키 == 복호화 키
      • Stream : 문자열 길이의 Stream을 생성해 bit단위로 암호화
      • Block : 하나의 블럭 단위로 암호화
    • 공개키 암호화 : 암호화 키 != 복호화 키
  • 단방향 암호화 : 암호화는 가능 / 복호화는 불가능!
    • Hash
      : 어떤 입력이든 고정된 길이의 문자열로 반환하여 암호화
        비밀번호 암호화에 주로 사용됨 / 양방향 암호화보다 빠름
        (Hash에 사용되는 Hash알고리즘은 공개되어 있어서 보안에 취약
              -> Salt를 넣거나, 여러번 Hash함수를 돌려서 강화해서 사용!)

Crypto

단순 Hash를 통한 암호화는 보안에 취약하기 때문에,
Salt값과 / 다중 Hash함수를 통해 보안성을 강화 해서 적용 할 예정 !
(출처 : 경선 블로그 - https://gngsn.tistory.com)


  • 사용하는 두가지 방법은 흐름제어를 직접해주냐 / 동기적 처리를 한 함수를 사용하느냐 의 차이!
    (pbkdf2Sync 방법이 더 편하고 최근의 것이다!)

    1) crypto.pbkdf2 + 흐름 제어
    (/modules/crypto.js) - promise작성 + 모듈로 분리

const crypto = require('crypto');

module.exports = {
  /* signup 시 password를 보내고 salt와 hashed를 반환 */
    encrypt: async (password) => {
        return new Promise(async (resolve, reject) => {
            try {
                const salt = (await crypto.randomBytes(32)).toString('hex');
                crypto.pbkdf2(password, salt.toString(), 1, 32, 'sha512', (err, derivedKey) => {
                    if(err) throw err;
                    const hashed = derivedKey.toString('hex');
                    resolve({salt,hashed});
                });
            } catch (err) {
                console.log(err);
                reject(err);
            }
        })
    },
  /* signin시 저장된 salt와 password를 통해 저장된 값과 같은지 확인용도 */
    encryptWithSalt: async (password, salt) => {
        return new Promise(async (resolve, reject) => {
            try {
                crypto.pbkdf2(password, salt, 1, 32, 'sha512', (err, derivedKey) => {
                    if(err) throw err;
                    const hashed = derivedKey.toString('hex');
                    resolve(hashed);
                });
            } catch (err) {
                console.log(err);
                reject(err);
            }
        })
    }
}

(사용할 파일.js) - async/await으로 흐름제어!

const encrypt = require('../modules/crypto');
...
    const {
        salt,
        hashed
    } = await encrypt.encrypt(password);
...

2) crypto.pbkdf2Sync
(/controllers/user.js) - signup

 const crypto = require('crypto');
...
/* signup -회원가입 */
 const salt = crypto.randomBytes(32).toString()
 const hashedPw = crypto.pbkdf2Sync(password, salt, 1, 32, 'sha512').toString('hex')

(/models/user.js) -signin

/* signin -로그인 */
 const hashedPw = crypto.pbkdf2Sync(password, userData[0].salt, 1, 32, 'sha512').toString('hex')

: 로그인 할 때에는 DB로 조회한 아이디의 해시된 비밀번호가 맞는지
  비교하기 위해 model에서 직접 사용했음 (컨틀롤러에서 해도 상관없음)


[ 주의 ]

회원가입 시 한 user의 DB에는 Salt값 / hash된password 두가지 모두 저장되어야 한다!

profile
Developer & PhotoGrapher

0개의 댓글