비대칭키 암호화 (Asymmetric Encryption)

비대칭키 암호화는 공개키 암호화라고도 불리며, 암호화와 복호화에 서로 다른 두 개의 키를 사용하는 암호화 방식.

장점:

  1. 키 분배가 용이하다 (공개키는 공개적으로 공유 가능)
  2. 높은 보안성을 제공한다.
  3. 디지털 서명 등 다양한 보안 기능 구현이 가능하다.

단점:

  1. 대칭키 암호화에 비해 처리 속도가 느리다.
  2. 더 많은 컴퓨팅 자원이 필요하다.

구현 예시:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes

class AsymmetricEncryption:
    def __init__(self):
        # 키 쌍 생성
        self.private_key = rsa.generate_private_key(
            public_exponent=65537,  # 일반적으로 사용되는 공개 지수
            key_size=2048  # 보안을 위한 충분한 키 크기
        )
        # 개인키로부터 공개키 추출
        self.public_key = self.private_key.public_key()
    
    def encrypt_message(self, message):
        """공개키로 메시지 암호화"""
        encrypted = self.public_key.encrypt(
            message.encode(),
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        return encrypted
    
    def decrypt_message(self, encrypted_message):
        """개인키로 메시지 복호화"""
        decrypted = self.private_key.decrypt(
            encrypted_message,
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        return decrypted.decode()

주요 특징

  1. 키 분배 문제 해결: 안전하지 않은 채널에서도 키를 교환할 수 있다.
  2. 높은 보안성: 공개키가 노출되어도 개인키가 안전하면 전체 시스템이 안전하다.
  3. 디지털 서명 가능: 메시지의 무결성과 발신자 인증에 사용된다.
  4. 느린 처리 속도: 대칭키 암호화에 비해 연산 속도가 느리다.

작동 원리

공개키와 개인키라는 두 개의 키를 사용한다.
공개키로 암호화한 데이터는 개인키로만 복호화할 수 있다.
개인키로 암호화한 데이터는 공개키로만 복호화할 수 있다.

  1. 키 생성 과정:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    def generate_key_pair(key_size=2048):
        """RSA 키 쌍 생성 과정의 상세 설명"""
        private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=key_size
        )
        public_key = private_key.public_key()
    
        # 키 정보 출력
        print(f"키 크기: {key_size} 비트")
        print(f"공개 지수: 65537 (일반적으로 사용되는 값)")
    
        return private_key, public_key
    
  2. 메시지 암호화 과정:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    def detailed_encryption_process(public_key, message):
        """암호화 과정의 단계별 설명"""
        # 1. 메시지를 바이트로 변환
        message_bytes = message.encode()
    
        # 2. 패딩 적용 (OAEP 패딩)
        # OAEP는 암호화에 무작위성을 추가하여 보안성을 높입니다
        padded_message = padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    
        # 3. 실제 암호화 수행
        encrypted = public_key.encrypt(
            message_bytes,
            padded_message
        )
    
        return encrypted
    
  3. 메시지 복호화 과정:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    
    def detailed_decryption_process(private_key, encrypted_message):
        """복호화 과정의 단계별 설명"""
        # 1. 패딩 설정 (암호화와 동일한 설정 사용)
        padded_message = padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    
        # 2. 복호화 수행
        decrypted = private_key.decrypt(
            encrypted_message,
            padded_message
        )
    
        # 3. 바이트를 문자열로 변환
        return decrypted.decode()
    

응용 분야

  1. 인증서 발급 및 관리 (PKI)
  2. 암호화된 이메일 (PGP)
  3. 안전한 통신 채널 구현:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class SecureCommunicationChannel:
    def __init__(self):
        self.encryption = AsymmetricEncryption()
    
    def send_secure_message(self, recipient_public_key, message):
        """수신자의 공개키로 메시지 암호화하여 전송"""
        encrypted_message = recipient_public_key.encrypt(
            message.encode(),
            padding.OAEP(
                mgf=padding.MGF1(algorithm=hashes.SHA256()),
                algorithm=hashes.SHA256(),
                label=None
            )
        )
        return encrypted_message
    
    def receive_secure_message(self, encrypted_message):
        """자신의 개인키로 메시지 복호화"""
        return self.encryption.decrypt_message(encrypted_message)
  1. 디지털 서명 구현:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class DigitalSignature:
    def __init__(self):
        self.encryption = AsymmetricEncryption()
    
    def sign_message(self, message):
        """메시지에 대한 디지털 서명 생성"""
        signature = self.encryption.private_key.sign(
            message.encode(),
            padding.PSS(
                mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH
            ),
            hashes.SHA256()
        )
        return signature
    
    def verify_signature(self, message, signature):
        """서명 검증"""
        try:
            self.encryption.public_key.verify(
                signature,
                message.encode(),
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256()
            )
            return True
        except:
            return False

보안 고려사항:

  1. 충분한 키 길이 사용 (최소 2048비트 이상)
  2. 안전한 난수 생성기 사용
  3. 적절한 패딩 방식 선택
  4. 개인키의 안전한 보관

이러한 비대칭키 암호화는 현대 인터넷 보안의 근간이 되는 기술이며, SSL/TLS, SSH, PGP 등 많은 보안 프로토콜에서 사용되고 있습니다.

이 주제에 대해 더 자세히 알고 싶으신 특정 부분이 있다면 말씀해 주세요.


참고 및 출처