웹 서비스/JavaScript

개발 삽질기 JS편 0001

로스군 2019. 1. 18. 14:43

19-01-18

python API서버와 AngularJS를 활용해 통신을 하기 위해 프로젝트를 진행하던중 보안이슈가 

발생하여 AngularJS단에서 Python과의 암복호화 통신이 필요하게 되었다. Python은 아래 사이트


https://cryptography.io/en/latest/  에서 참고하여  

암호 : AES-128, 모드 : CBC, 패딩 :PKCS7로 셋팅해 암복호화를 구현했다.


JavaScript는 CryptoJS를 사용하여 간단하게 구현할 수 있었다.


구현 예제는 아래

https://cryptojs.gitbook.io/docs/



여기서 문제가 발생했다.

분명 똑같이 key, iv, mode, padding 동일하게 입력했는데

출력이 다르다는 것이었다.


CryptoJS는 암호화를 할때마다 다른 결과를 출력했고, 

Python측은 동일한 암호문을 출력했다.


또한 CryptoJS측은 암호문의 길이가 예사롭지 않게 길었고

Python 측은 그렇게 크게 길지 않았다. 

(짧은 길이 기준)


지금부터 삽질이 시작되는데

암호화 알고리즘에 대해서 잘 알지 못해 AES가 무엇인가에 대해서 공부해보았고

대충 흐름을 파악할 수 있었다.  물론 아직 자세히 알지는 못한다..


그리고 동료가 수정해보는 쪽과 stackOverflow에서 찾아보니 key, iv  format에 다루고있었고

확실히 암호 알고리즘은 똑같고 개발자가 변화를 줄 수 있는 폭은 형태였다. 따라서 

포맷(문자열 인코딩 등!)을 중심으로 잡고 여러가지 시도를 해본 결과 PYTHON과 CryptoJS 암/복호화에 성공하였다.


아래 소스 참고

  function encrypt(pText, init_key, init_iv) {

    var key = CryptoJS.enc.Utf8.parse(init_key);

    var iv = CryptoJS.enc.Utf8.parse(init_iv);


    var cipherData = CryptoJS.AES.encrypt(pText, key, {

      iv: iv,

      mode: CryptoJS.mode.CBC,

      padding: CryptoJS.pad.Pkcs7,

      format: CryptoJS.format.OpenSSL

    });


    return cipherData

  }


  function decrypt(cipherText, init_key, init_iv) {

    var key = CryptoJS.enc.Utf8.parse(init_key);

    var iv = CryptoJS.enc.Utf8.parse(init_iv);


    var Data = CryptoJS.AES.decrypt(cipherText, key, {

      iv: iv,

      mode: CryptoJS.mode.CBC,

      padding: CryptoJS.pad.Pkcs7,

      format: CryptoJS.format.OpenSSL

    });


    return Data

  }


  var ct = encrypt('aaa',key,iv).toString();

  console.log('암호화:' + ct);

  console.log('복호화:' + decrypt(ct, key,iv).toString(CryptoJS.enc.Utf8));



///CRYPTO-JS 구현 문서를 계속 찾아보았다.

기본 설정이 아래와같이 셋팅되어있었다.

MODE : CBC

PADDING : PKCS7

FORMAT : OPENSSL


수정하면 


  function encrypt(pText, init_key, init_iv) {

    var key = CryptoJS.enc.Utf8.parse(init_key);

    var iv = CryptoJS.enc.Utf8.parse(init_iv);


    var cipherData = CryptoJS.AES.encrypt(pText, key, {

      iv: iv

    });


    return cipherData

  }


  function decrypt(cipherText, init_key, init_iv) {

    var key = CryptoJS.enc.Utf8.parse(init_key);

    var iv = CryptoJS.enc.Utf8.parse(init_iv);


    var Data = CryptoJS.AES.decrypt(cipherText, key, {

      iv: iv

    });


    return Data

  }


  var ct = encrypt('aaa',key,iv).toString();

  console.log('암호화:' + ct);

  console.log('복호화:' + decrypt(ct, key,iv).toString(CryptoJS.enc.Utf8));


;;;; 결국 KEY와 IV 값 인코딩이 PYTHON과 다르게 들어가서 발생했던 문제였던것 같다.