RSA를 이용한 전자서명(디지털서명) 구현
1. RSA를 이용한 전자서명(디지털서명)
(1) RSA 전자서명 알고리즘
▶ 예전에 정리한 내용이 있어서 아래 URL을 통해 확인이 가능하다.
▶ 참고 : https://ccurity.tistory.com/93
(2) 전자서명(디지털서명)의 방법
[1] 메세지 전체에 서명
▶ 메모리 비용이 많이 든다.
[2] 인증자(authenticator)에 대한 서명
▶ 작은 비트블록인 인증자에 서명을 할 경우 인증자 변경 없이 문서만 변경하는 것은 불가능하다.
▶ 인증자 부분만 서명을 하기 때문에 기밀성은 보장할 수 없다.
[3] 메세지의 해시값에 서명
▶ 해시와 해시를 암호화 한 것을 공개키로 풀어서 비교가 가능하다.
※ Hmac을 사용하면 안되는 이유는?
▶ 키를 공통으로 쓰기 때문에 중간에 변경하고 다시 암호화해서 전송하면 의미가 없기 때문이다.
▶ 즉, 중간에서 얼마든지 변조될 수 있다.
▶ 중간자 공격을 이용하면 디지털서명도 해커가 개인키와 공개키 세트를 새로 만들어 사용자에게 전송하면 위험할 수 있다.
▶ 그래서 제 3자(믿을 수 있는 인증기관)를 통해 정말 그 사람의 공개키가 맞는지 인증하는 것이 공인인증서이다.
▶ 공인인증서에는 공개키와 공개키가 맞다는 제 3보증기관의 디지털서명(보증기관의 개인키로)이 포함되어 있다.
※ 메세지인증과 디지털서명 중 부인방지가 가능한 것은?
▶ MAC값을 계산할 수 있는 키(대칭키)는 송신자와 수신자가 모두 가지고 있다.
▶ 서로 자기가 계산하지 않았다고 주장하기 때문에 부인이 가능하다.
▶ 그러나 디지털서명은 서명을 작성할 수 있는 키(개인키)는 송신자만 가지고 있다.
▶ 즉, 송신자만이 서명을 할 수 있기 때문에 서명을 내가 하지 않았다고 주장할 수 없다.
※ 공개키 인증서
▶ 공개키에 디지털서명을 추가한 것을 말한다.
(3) 전자서명
[1] 소스
from Crypto.PublicKey import RSA from Crypto.Hash import SHA256 def main(): # 전자서명은 내 private_key로 sign(서명) # 내 public_key로 verify(검증) fin = open('private_key.pem', 'rb') private_key = RSA.importKey(fin.read()) fin.close() msg = b'I love you' h = SHA256.new(msg).digest() # 내가 받은 메세지의 해시를 추출 sign = private_key.sign(h, '') # 해시를 개인키로 전자서명 print('1. hash : {}'.format(h)) print('2. sign : {}'.format(sign)) my_msg = msg my_sign = sign # 메세지와 해시의 사본을 생성 my_h = SHA256.new(my_msg).digest() # my_msg의 해시를 구함 fin = open('public_key.pem', 'rb') public_key = RSA.importKey(fin.read()) fin.close() if public_key.verify(my_h,my_sign): #전자서명이 붙어있는 해시와 내가 문자열에서 추출한 해시가 같은지 # ms_msg의 해시와 해시로 서명한 내용이 같은지 비교 print('verify!!') else: print('Denied!!') if __name__ == '__main__': main()
[2] 시연
(4) pickle
▶ python3 내 pickle모듈이 있다.
▶ 이 모듈은 메모리 내에 저장된 객체를 문자열로 바꾼다음 저장할 수 있다.
[1] 시리얼라이즈
▶ 메모리에 존재하는 객체
[2] 디시리얼라이즈
▶ 죽어있는 정보를 메모리에 올리는 것
[3] pickle을 사용하는 이유?
▶ 메모리 안에 있는 객체의 정보를 파일에 저장했다가 다시 메모리에 올릴 수 있다.
[4] 소스
import pickle def main(): # 시리얼라이즈 하는 방법 a = (1, 2, 3, 4) print(a) pickle.dump(a, open('test.txt', 'wb+')) # 디시얼라이즈 하는 방법 b = pickle.load(open('test.txt', 'rb')) print(b) if __name__ == '__main__': main()
[5] 시연
(5) pickle을 이용한 전자서명
[1] 소스
from Crypto.PublicKey import RSA from Crypto.Hash import SHA256 def main(): msg = b'I love you' private_key = RSA.importKey(open('private_key.pem', 'rb').read()) # 개인키를 읽어와서 추가한다. h = SHA256.new(msg).digest() # msg에 대한 해시를 구한다. sign = private_key.sign(h, '') # 해시로 서명을 한다. pickle.dump(sign, open('my.sign', 'wb+')) # sign한 것(객체)를 파일로 저장한다. # 전송준비 rmsg = msg rh = SHA256.new(rmsg).digest() # 파일에서 전자서명을 로드 rsign = pickle.load(open('my.sign', 'rb')) # 보낸사람의 공개키 로드 rpublic_key = RSA.importKey(open('public_key.pem', 'rb').read()) # 검증 if rpublic_key.verify(rh, rsign): print('Verify !!') else: print('Denied !!') if __name__ == '__main__': main()
[2] 시연
'Theory > Cipher protocol' 카테고리의 다른 글
Ciphertext Only Attack(암호문 단독 공격) 구현 (0) | 2019.05.31 |
---|---|
Known Plaintext Attack(기지 평문 공격) 구현 (0) | 2019.05.31 |
RSA공개키를 이용한 암호화 구현 (0) | 2019.05.30 |
3DES를 이용한 암호화 (0) | 2019.04.11 |
시저암호 (0) | 2019.03.19 |
댓글