정보보안

비대칭 암호화

asd135 2025. 5. 27. 02:27
728x90

비대칭 암호화 방식의 필요성

대칭 암호화 방식의 키 배포 문제에 대한 보완책 필요

 

비대핑 암호화 방식

디피-헬만 키 교환: 소수(prime)를 이용한 나머지(mod) 연산을 이용 -> 통신을 통해 미리 배포되지 않은 새로운 비밀키 s를 공유하는 것이 목표

 

과정

  1. 공개된 숫자 p와 g 설정
  2. 앨리스 : 자신의 개인키 a에서 숫자 A를 계산
  3. 밥 : 자신의 개인키 b에서 B를 계산
  4. 앨리스 : 밥이 전달한 B와 자신의 개인키 a를 이용하여 비밀키 s를 계산
  5. 밥 : 앨리스가 보내준 A와 자신의 개인키 b를 이용하여 비밀키 s를 계산

 

RSA

1977년 미국의 로널드 리베스트(Ronald Rivest), 아디 샤미르(Adi Shamir), 레오나르도 애들먼 (Leonard Adleman)의 공동 고안된 비대칭 암호화의 대표적인 알고리즘

암호화와 전자서명을 모두 처리할 수 있어 전자상거래, SSL, 디지털 서명 등에서 많이 사용됨

 

비대칭 암호화 방식1

공개키로 암호화, 개인키로 복호화

암호화된 메시지는 개인키로만 복호화 가능 -> 기밀성 보장

다른 사람이 중간에서 도청할 수 없음

중간에서 메시지를 가로챘더라도 암호화된 메시지를 복호화할 수 없음

 

예시: 앨리스가 밥에게 메시지를 보내고 싶을 때

1. 밥은 자신의 공개키를 앨리스에게 전달한다. -> 이 공개키는 누구나 볼 수 있음

2. 앨리스는 밥의 공개키로 메시지를 암호화한다. -> 암호화된 메시지를 밥의 개인키 없이는 복호화 불가

3. 밥은 암호문을 받은 후 자신의 개인키로 복호화한다. -> 원래의 평문을 볼 수 있음

 

위 예시에서 핵심 내용: 공개키로 암호화된 데이터는 오직 해당 공개키에 대응하는 개인키로만 복호화할 수 있음, 공개키는 모두가 아는 정보지만, 개인키는 오직 수신자만 알고 있는 정보

 

비대칭 암호화 방식2

개인키로 암호화, 공개키로 복호화

복호화가 되었다는 것은 그 개인키를 가진 사람이 보냈다는 확실한 증거가 됨

 

예시: 앨리스가 계약서를 밥에게 보낼 때, 본인이 보낸 것임을 증명하고 싶음

1. 앨리스는 자신의 개인키로 메시지를 암호화함 -> 전자서명

2. 밥은 앨리스의 공개키로 암호화된 내용을 복호화함 -> 복호화가 성공했다는 뜻은 이 메시지는 앨리스가 만들었다는 의미

 

설명

개인키는 앨리스만 가지고 있음

따라서 메시지를 암호화한 사람은 오직 앨리스뿐

메시지가 앨리스의 공개키로 복호화되면, 앨리스가 보낸 것이 맞다는 디지털 증거가 됨

->전자상거래에서 기업 간 주문이나 계약에서도 중요한 법적 증거 역할 

 

전자서명

개념: 개인키로 암호화, 공개키로 복호화

정의: 원본 메시지에 대한 해시 값을 서명자의 개인키로 암호화하는 것 -> 메시지에 대한 인증, 부인방지 및 메시지 무결성 검증 

 

전자서명의 약점

공개키가 진짜 그 사람의 것인지 검증하는 문제, 신뢰성 문제가 존재함

 

예시 상황: 만약 누군가가 가짜 공개키를 앨리스의 것처럼 위조해서 유포하면?

  • 그 사람은 자기 개인키로 서명을 만들고
  • 수신자는 위조된 공개키로 그 서명을 확인 -> 전자서명 위조가 가능

해결책

공개키 인증서(PKC, Public Key Certificate): 신뢰할 수 있는 인증 기관(CA, Certification Authority)을 이용하여 신뢰할 수 있는 안전한 공개키를 제공

 

인증서 사용 방법

사용자의 공개키에 사용자의 식별 정보를 추가하여 만든 일종의 전자 신분증

 

Step 1: 인증서 등록 및 배포(발급/유통 단계)

이 단계에서는 사용자가 자신의 공개키를 인증받고 배포하는 과정을 거침

  1. 사용자가 CA에 인증 요청
  2. CA가 사용자의 신원을 확인
  3. CA가 인증서 발급
  4. 인증서 배포(OS의 인증서 저장소에 등록, USB 저장 등)

Step 2: 인증서 검증 및 공개키 사용(검증/활용 단계)

이 단계에서는 수신자가 인증서를 검증한 후, 안심하고 공개키를 사용한다.

  1. 인증서 수신(이메일, HTTPS 접속 시 서버가 인증서 제공)
  2. 인증서의 유효성 검증
  3. 인증서에서 공개키 추출

공개키 기반 구조(PKI: Public Key Infrastructure): 공개키를 효과적으로 사용하여 안전한 암호화와 전자서명 기능 등을 제공하는 보안 환경(예: 인터넷 뱅킹에서 사용되는 공인인증서)

 

클라이언트

import socket
from nacl.public import PrivateKey, Box, PublicKey

# 클라이언트 비밀키/공개키 생성
client_sk = PrivateKey.generate()
client_pk = client_sk.public_key

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("127.0.0.1", 9999))

# 서버 공개키 수신
server_pk_bytes = sock.recv(1024)
server_pk = PublicKey(server_pk_bytes)

# 클라이언트 공개키 전송
sock.sendall(bytes(client_pk))

# Box 생성
client_box = Box(client_sk, server_pk)

# 5. 메시지 입력 및 암호화
msg = input("입력: ").encode()
enc_msg = client_box.encrypt(msg)

sock.sendall(enc_msg)

echo_plain = client_box.decrypt(sock.recv(1024))
print("echo-수신자 B가 보낸 메시지 복호화:", echo_plain.decode())
# 종료
sock.close()

 

서버

import socket
from nacl.public import PrivateKey, Box, PublicKey

# 서버 비밀키/공개키 생성
server_sk = PrivateKey.generate()
server_pk = server_sk.public_key

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("", 9999))
sock.listen()
print("서버 시작...")

conn, addr = sock.accept()
print(f"송신자A 접속: {addr}")

# 서버 공개키 전송
conn.sendall(bytes(server_pk))

# 클라이언트 공개키 
client_pk_bytes = conn.recv(1024)
client_pk = PublicKey(client_pk_bytes)

# Box 생성
server_box = Box(server_sk, client_pk)

# 암호화된 데이터
enc_data = conn.recv(1024)
print("송신자 A가 보낸 암호화된 메시지:", enc_data)
 
plain_data = server_box.decrypt(enc_data)
print("수신자 B가 받은 복호화된 메시지:", plain_data.decode())

# 암호화해서 에코
conn.sendall(server_box.encrypt(plain_data))

# 서버 종료
conn.close()
sock.close()