ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [개발] Python으로 공인인증서 로그인 과정 확인
    카테고리 없음 2015. 1. 31. 14:50

    비대칭키를 이용한 암호/서명

    - 비대칭키: 개인키 및 공개키로 나누어 활용

    - 공개키: 암호화 작업만 할 수 있음. 누구에게나 공개되어도 상관 없음

    - 개인키: 복호화 작업을 위해 사용. 공개되면 안되는 키

    디지털 서명

    - '원래 자료'를 '해쉬'로 만든 다음,

    - ‘개인 키'로 해당 해쉬 값을 ’암호화' 하고 (서명),

    - 다른 사람들은 '원래 자료'를 '해쉬'로 만든 다음,

    - 서명 값을 '공개 키'로 '복호화' 해서 비교하여

    - 두 해쉬 값을 비교하여 일치하면 서명이 유효함.

    즉 인증서를 통한 로그인시

    - 사용자: 인증서의 고유 번호 + challenge 받은 메시지에 대한 서명 값을 server로 전송

    - 서버: 해당 고유 번호에 등록된 공개키로 이 사용자가 서명한 값이 맞는지 확인 (검증은 공개키로 가능. 검증에 성공했다는 것은 이 사용자가 개인키를 가지고 있다는 이야기)

    (실제 서버단에서는 어떤 다른 추가적인 방법이 있는지는 알 수 없으나 아무튼 정해서

    공인인증서 관련 기술들

    - http://www.rootca.or.kr/kor/standard/standard01B.jsp 를 참고

    - 개인키: signPri.key 에 암호화 되어 들어있다.

    - 공개키: signCert.der 에 들어있다.

    - 인증서 발급처 마다 조금씩은 다르지만, 은행에서 발급 받은 yessign 공인인증서를 이용하여 테스트

    공개키 파일

    - signCert.der

    - asn1 형식

    - 안에 다시 asn1 형식

    - 해당 파일이 PKCS#1인데 pub key 만 있었음

    개인키 파일

    - signPri.key

    - PKCS#5 의 PBKDF1방식을 이용하여 복호화 한다. (키 파일에서 salt, integration count 를 구하고, 비밀번호는 공인인증서 비밀번호)

    위 두 파일에 대한 처리 방법은 아래 링크를 참고

    - https://gist.github.com/twkang/f5acf360c67ea0bf3f55

     

    테스트해봅시다.

    (파이선 코드)

    원본(3): “abc”

    sha256(64H/32B) ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

    EME-PKCS1-v1_5 padding 처리 (msg = ‘abc’, key 길이 = 256, hash=sha256)

    0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

    (앞에 \x00\x01 붙이고, \xff로 쭉 채우고 \x00 붙이고 해쉬 종류에 따른 prefix 붙이고 abc에 대한 해쉬값을 붙인다.)

    이 값을 개인키를 이용하여 ‘복호화’ 한다.

    (암호화도 안했는데 왜 복호화부터 하냐고 묻지말자. 그냥 이렇게 정한것이다. 정말 PKI기반 디지털 서의 이론적인 원리가 궁금하다면 http://en.wikipedia.org/wiki/Digital_signature#How_they_work 를 참고하자.)

    -> (256바이트/512Hex 데이터)

    이 값이 서명값이고, 실제 플러그인에서 만들어 낸 서명문의 서명값과 일치한다.

    (실제 플러그인 구동)

    원본: SignData(‘abc’,’’,0)

    결과값(3760H):

    -> 3082...

    여기서 뽑아낸 hash (512H/256B)

    -> 26...76

    이 hash에 대한 pubkey의 encrypt 결과 (510H/255B)

    -> 01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003031300d060960864801650304020105000420ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

    서명(sign) : 복호화(decrypt)

    검증(verify) == 암호화 후 메시지 같은지 비교

    <실험>

    서명 데이터를 다르게 했을 때 두 값이 달랐는데, 하나는 pkcs7-data(이게 아마 format에 맞춘게 아닐까), 나머지 하나가 해쉬.. 근데 그러면 pkcs7-data를 sign해야되나...

    #1 mitmproxy 를 이용하여 트래픽 분석

    #2 트래픽 일부 분석

    #3 인증서 구조 분석

    #4 서명 결과 분석

    - ***** 사이트에서 로그인 시도

    - yessignCrypto.js 스크립트에서 서명

    - inputStr 에 서명할 데이터 포함 (timestamp 포함한 form data)

    - yessignCrypto.SignData(inputStr, ssn, option) 을 통해 서명 (ssn, option에는 blank string)

    - 공인인증서 로그인 창이 뜬 다음 서명 데이터 나온다 (여러번 요청해도 똑같은 데이터가 나옴 - 즉 서명 단계에서는 더이상 랜덤 값을 넣지 않는다)

    - 이 결과(A)에 몇 가지 form data 를 추가하여 POST 요청

    #5 결과(A)에 대한 분석

    - 길이는 3966 바이트 (어느정도 변화 가능 - hex encoded 데이터)

    - hex decode 결과는 약 1983 바이트 결과(A-1)

    - 결과(A-1)은 30 82 로 시작하는 0x3082 == ASN.1 Sequence (http://etherhack.co.uk/asymmetric/docs/rsa_key_breakdown.html)

    - 이 결과(A-1)를 파일로 저장하여 openssl 로 열어봅시다

    - $ openssl asn1parse -in FILENAME -inform der

    - pkcs7-data 로 174바이트의 hex encoded 데이터 (hex decode 후 euc-kr 로 decode시 원본 서명 텍스트 나옴)

    - rsaEncryption 로 512바이트의 hex encoded 데이터 (hex decode 후 256바이트의 raw data)

    - sha256WithRSAEncryption 로 2048비트(256바이트)의 이진수 데이터 (raw data). RSA암호 후 이걸로 해쉬하면 이게 나오나

    - 특별히 이름은 없는데 270바이트짜리 2진수 raw data도 존재. 서명 단계에서 원본값을 변조한 결과 변경되지 않으므로 무시.

    - 즉 sha256WithRSAEncryption 값이 서명 데이터임을 알 수 있음

    #6 서명데이터(256바이트)에 대한 분석

    - object tag를 통해 active x 를 호출하는 과정에서, 같은 인증서를 이용한 경우 해쉬 값에는 오로지 메시지만 영향을 주는 것을 확인

    -> 즉 메시지에 대한 서명값

    #* 기타

    - 전자 서명문은 PKCS#7 을 이용

Designed by Tistory.