nukw0n
찐이의 개발 연결구과
nukw0n
전체 방문자
오늘
어제
  • 분류 전체보기 (38)
    • 유연해지기 (21)
      • React.js (11)
      • Javascript (5)
      • webpack & babel (1)
      • etc. (4)
      • Next.js (0)
    • 단단해지기 (13)
      • Algorithm (9)
      • Computer Science (4)
    • 속닥속닥 (4)
    • 책읽는 남자 (0)

블로그 메뉴

    공지사항

    인기 글

    태그

    • React
    • useBuiltIns
    • history API
    • Batching
    • intersectionobserver api
    • vanilla spa
    • React 18
    • 프로그래머스
    • 콜백 ref
    • Auto Batching
    • bfs
    • 백준
    • sass vs postcss
    • vallia 라우터
    • javascript
    • 알고리즘
    • fallback UI
    • error 안 뜸
    • dfs
    • Error Boundary

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    nukw0n

    찐이의 개발 연결구과

    [React.js] crypto-js를 이용한 패스워드 암호화
    유연해지기/React.js

    [React.js] crypto-js를 이용한 패스워드 암호화

    2021. 4. 22. 18:06

     

    서론

    진행 중인 프로젝트에서 간단한 익명 로그인을 구현하게 되었다.

     

    게시글 작성 시 아이디와 패스워드를 입력받은 뒤 해당 게시물의 수정이나 삭제 요청에는 아이디 패스워드를 확인하는 구조이다.

     

    처음에는 firebase의 실시간 데이터베이스를 사용해 게시물의 정보와 아이디, 패스워드 값을 그대로 저장했다.

    하지만 유저가 입력한 정보를 데이터베이스에 전송하는 과정에서 아이디와 패스워드가 그대로 드러나기 때문에 절대 이렇게 구현을 마쳐서는 안 된다. 그저 패킷을 열어보기만 해도 유저의 정보가 유출되기 때문에...

     

    아무리 간단한 익명 로그인이어도 '챙길 건 챙기자! '라는 마인드로 패스워드의 암호화를 진행하게 되었다.

    암호화

    crypto-js 패키지를 사용했고 그중 PBKDF2 알고리즘을 선택했다.

     

    PBKDF2는 salt라는 것을 사용해서 패스워드를 공격자가 유추해내기 더 어렵게 만든다.

     

    그저 패스워드에 해시를 적용해서 사용하는 것보다는 PBKDF2를 사용하는 것이 보안강도가 높다는 것이다.
    해시만 적용해서 사용하면 레인보우 테이블, 사전 공격, 브루트 포스 등 뭐 아무튼 공격자들이 게시글의 패스워드를 비교적 쉽게 찾아낼 수 있게 된다.

    구현

    import CryptoJS from 'crypto-js';
    
    const pwdEncrypt = (pwd, originSalt, originIv) => {
      const salt = originSalt || CryptoJS.lib.WordArray.random(128 / 8).toString(CryptoJS.enc.Hex);
      const iv = originIv || CryptoJS.lib.WordArray.random(128 / 8).toString(CryptoJS.enc.Hex);
    
      const iterations = 10000;
    
      const key512Bits10000Iterations = CryptoJS.PBKDF2('1234', CryptoJS.enc.Hex.parse(salt), {
        keySize: 512 / 32,
        iterations,
      });
    
      const encrypted = CryptoJS.AES.encrypt(
        pwd,
        key512Bits10000Iterations,
        { iv: CryptoJS.enc.Hex.parse(iv) },
      );
    
      return {
        encryptedPwd: encrypted.toString(),
        salt,
        iv,
      };
    };
    
    export default pwdEncrypt;

    처음 게시글을 작성할 때에는 랜덤 한 salt와 initial vector을 생성해서 작동하도록 했다.

     

    CryptoJS.PBKDF2('1234', CryptoJS.enc.Hex.parse(salt) ... )

    이 부분에서 1234는 Secret PassPhrase인데 실제로 사용할 때에는 이렇게 쉽고 예측 가능한 값을 사용하면 안 된다.

    아무튼 iteration을 반복하며 Secret PassPhrase에 salt를 가미하여 새로운 키를 생성해낸다.

     

    이 키를 통해 AES 암호화 알고리즘으로 encrypt 하면 최종 암호화된 패스워드가 완성된다.


    {
        "encryptedPwd": "0h+AJgRySA7pAy3abppETQ==",
        "iv": "444617aa9550d924a13597b7b5be928c",
        "salt": "1cc9864bdcbd34b9d9d9fd5db33ba1dd"
    }

    firebase에 저장된 게시글의 정보

     

    pwdEncrypt 함수가 반환하는 객체 값은 위와 같이 데이터베이스에 password 객체로 할당되었다.

     

    iv와 salt를 데이터베이스에 같이 할당해준 이유는 유저가 올바르게 입력한 패스워드에 대하여 동일한 iv와 salt를 사용해서 암호화해야 데이터베이스에 저장되어있는 것과 동일한 암호문이 나오기 때문이다.

     


    이렇게 구현해본 간단한 익명 로그인의 동작 방식은 이렇다.

     

    1. 처음 게시글을 작성할 때 데이터베이스에 pwdEncrpyt 함수를 통해 암호화한 패스워드를 저장한다.
    2. 해당 게시글의 수정/삭제를 시도한다면 아이디와 패스워드를 요구한다.
    3. 해당 게시글의 데이터베이스에서 iv와 salt를 가져와 입력된 패스워드에 대해 1번과 같은 방식으로 암호화한다.
    4. 3의 결괏값인 encryptedPwd와 데이터베이스에 저장된 encryptedPwd가 같은지 비교한다.
    const checkIdPwValid = () => {
        const { iv, salt, encryptedPwd: originPwd } = savedPw;
        const inputPwd = pwdEncrypt(password, salt, iv);
    
        if (savedAuthor === author && originPwd === inputPwd.encryptedPwd) {
            // Do Something !
        }
      };

    마무리

    crypto-js docs를 찾아보며 코드를 작성했는데 사실 독스의 설명이 부실한 감이 없잖아 있다.

    따로 찾아보면서 pwdEncrypt 함수를 작성했고 실제로 잘 동작했다. 

     

    혹 작성한 내용 중 틀린 부분이 있다면 얼마든지 지적해주세요!
    감사합니다,

     

    '유연해지기 > React.js' 카테고리의 다른 글

    리액트 절대경로 설정 및 모듈/경로 별명 짓기 with CRA (absolute path, path alias)  (0) 2021.10.21
    [React.js] Error Boundary와 Fallback UI 에 대하여  (0) 2021.10.08
    [React.js] useEffect, cleanUp, deps, unMount에 대하여  (0) 2021.09.29
    [React.js] useRef와 useState의 용도와 차이  (0) 2021.09.07
    [React.js] 고차 컴포넌트 HoC 에 대하여  (0) 2020.09.13
      '유연해지기/React.js' 카테고리의 다른 글
      • [React.js] Error Boundary와 Fallback UI 에 대하여
      • [React.js] useEffect, cleanUp, deps, unMount에 대하여
      • [React.js] useRef와 useState의 용도와 차이
      • [React.js] 고차 컴포넌트 HoC 에 대하여
      nukw0n
      nukw0n
      프론트엔드 개발자 권혁진입니다.

      티스토리툴바