Key Exchange
Diffie-Hellman (DH)
과정
공통 파라미터
| 기호 | 의미 | 공개 여부 |
|---|---|---|
| ( p ) | 큰 소수 (Prime modulus) | 공개 |
| ( g ) | 생성자 (Generator) | 공개 |
Alice(송신자) 파라미터
| 항목 | 기호 / 수식 | 의미 | 공개 여부 |
|---|---|---|---|
| 개인 키 | a | Alice만 아는 비밀 정수 | 비공개 |
| 공개 키 | A = g^a mod p | Alice가 계산한 공개 값 | 공개 |
| 공유 비밀 계산 | S = B^a mod p | Bob의 공개 키 사용 | 비공개 |
Bob (참여자2) 파라미터
| 항목 | 기호 / 수식 | 의미 | 공개 여부 |
|---|---|---|---|
| 개인 키 | b | Bob만 아는 비밀 정수 | 비공개 |
| 공개 키 | B = g^b mod p | Bob이 계산한 공개 값 | 공개 |
| 공유 비밀 계산 | S = A^b mod p | Alice의 공개 키 사용 | 비공개 |
핵심
DH 실습
코드
import secrets
import hashlib
class Participant:
def __init__(self, name, p, g):
self.name = name
self.p = p
self.g = g
self.private_key = self._generate_private_key()
self.public_key = pow(self.g, self.private_key, self.p)
self.shared_key = None
def _generate_private_key(self):
return secrets.randbelow(self.p - 2) + 2
def _derive_key_byte(self):
digest = hashlib.sha256(str(self.shared_key).encode()).digest()
return digest[0]
def get_public_key(self):
return self.public_key
def derive_shared_key(self, other_public_key):
self.shared_key = pow(other_public_key, self.private_key, self.p)
def encode(self, message):
if self.shared_key is None:
raise ValueError("Shared key not established")
key_byte = self._derive_key_byte()
plaintext_bytes = message.encode("utf-8")
encoded = bytes(b ^ key_byte for b in plaintext_bytes)
print(f"[{self.name} → SEND]")
print(f"Original (HEX) : {plaintext_bytes.hex()} ({message})")
print(f"Encoded (HEX) : {encoded.hex()}")
return encoded
def decode(self, encoded_message):
if self.shared_key is None:
raise ValueError("Shared key not established")
key_byte = self._derive_key_byte()
decoded_bytes = bytes(b ^ key_byte for b in encoded_message)
decoded = decoded_bytes.decode("utf-8")
print(f"[{self.name} ← RECV]")
print(f"Original (HEX) : {encoded_message.hex()}")
print(f"Decoded : {decoded_bytes.hex()} ({decoded})")
return decoded
p = int(
"""
FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1
29024E088A67CC74020BBEA63B139B22514A08798E3404DD
EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245
E485B576625E7EC6F44C42E9A63A36210000000000090563
""".replace(
"\n", ""
),
16,
)
g = 2
alice = Participant("Alice", p, g)
bob = Participant("Bob", p, g)
alice.derive_shared_key(bob.get_public_key())
bob.derive_shared_key(alice.get_public_key())
message = "hello"
bob.decode(alice.encode(message))
결과
[Alice → SEND]
Original (HEX) : 68656c6c6f (hello)
Encoded (HEX) : cec3cacac9
[Bob ← RECV]
Original (HEX) : cec3cacac9
Decoded : 68656c6c6f (hello)