Key Exchange

codakcodak·2026년 1월 6일

Security

목록 보기
2/4

Key Exchange

  • 두 주체가 동일한 암호화 키를 안전하게 공유하거나 생성하기 위한 암호학적 과정
    • Out-of-Band: 암호화 키를 네트워크 통신 경로와는 별도의 안전한 채널을 통해 전달하는 방식
    • In-Band: 동일한 네트워크 통신 경로를 사용해 키를 안전하게 교환하거나 생성하는 방식
      • RSA Key Exchange: 상대방의 공개키로 암호화해서 보내는 방식
      • Diffie-Hellman (DH)
      • Elliptic Curve Diffie-Hellman (ECDH)

Diffie-Hellman (DH)

  • Diffie-Hellman(DH)은 두 통신 주체가 공개된 수학적 파라미터를 사용해, 비밀 키를 직접 전달하지 않고 동일한 대칭 키를 생성하는 키 합의(Key Agreement) 알고리즘

과정

  • 공통 파라미터

    기호의미공개 여부
    ( p )큰 소수 (Prime modulus)공개
    ( g )생성자 (Generator)공개
  • Alice(송신자) 파라미터

    항목기호 / 수식의미공개 여부
    개인 키aAlice만 아는 비밀 정수비공개
    공개 키A = g^a mod pAlice가 계산한 공개 값공개
    공유 비밀 계산S = B^a mod pBob의 공개 키 사용비공개
  • Bob (참여자2) 파라미터

    항목기호 / 수식의미공개 여부
    개인 키bBob만 아는 비밀 정수비공개
    공개 키B = g^b mod pBob이 계산한 공개 값공개
    공유 비밀 계산S = A^b mod pAlice의 공개 키 사용비공개

핵심

B^a mod p = g^(ab) mod p = A^b mod p

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)
profile
숲을 보는 코더

0개의 댓글