Public Key와 Private Key의 역할

Public Key와 Private Key의 역할

Python
Public Key와 Private Key의 역할
Author

gabriel yang

Published

September 30, 2024


디지털 서명(Digital Signature)은 메시지의 무결성을 보장하고, 송신자의 신원을 확인할 수 있는 암호화 기술입니다. 이 과정에서는 공개 키(public key)개인 키(private key)를 사용하여 서명을 생성하고, 이를 검증할 수 있습니다. 이 글에서는 Python을 사용해 공개 키와 개인 키를 생성하고, 이 키들로 서명을 생성 및 검증하는 방법을 설명합니다.

1. 공개 키와 개인 키의 역할

  • 개인 키 (Private Key): 송신자가 자신만이 알고 있는 비밀 키로, 이 키를 사용해 데이터를 암호화하거나 서명을 생성합니다.
  • 공개 키 (Public Key): 수신자가 알고 있는 공개 키로, 이 키를 사용해 개인 키로 생성된 서명을 검증하거나 암호화된 데이터를 복호화합니다.
  • 서명 프로세스:
  1. 송신자는 개인 키로 서명을 생성합니다.
  2. 수신자는 공개 키로 서명을 검증하여 메시지가 변조되지 않았음을 확인합니다.

공개 키(public key)개인 키(private key)는 비대칭 암호화 방식의 핵심 요소입니다. 이 두 가지는 서로 밀접한 수학적 관계를 가지며, 이를 이용해 데이터를 암호화하고 서명을 검증하는 데 사용됩니다. 이 관계는 주로 RSA나 ECC 같은 암호화 알고리즘을 통해 구현되며, 비대칭 키 암호화의 주요 특성은 다음과 같습니다.

a. 공개 키와 개인 키의 역할

  • 공개 키 (Public Key): 이름 그대로 누구나 알 수 있는 키입니다. 주로 데이터를 암호화하거나, 개인 키로 생성된 서명을 검증하는 데 사용됩니다.
  • 개인 키 (Private Key): 소유자만이 알고 있는 비밀 키입니다. 개인 키는 데이터를 복호화하거나, 서명을 생성하는 데 사용됩니다. 절대로 타인과 공유되지 않아야 합니다. 이 두 키는 한 쌍으로 존재하며, 그 관계는 아래와 같습니다.

b. 공개 키와 개인 키의 수학적 관계

  • 비대칭성: 공개 키로 암호화된 데이터는 개인 키로만 복호화할 수 있습니다. 마찬가지로, 개인 키로 서명한 데이터를 공개 키로만 검증할 수 있습니다.
  • 수학적 연관성: 공개 키와 개인 키는 수학적으로 연결되어 있지만, 공개 키로부터 개인 키를 유추하기는 매우 어렵습니다. 이는 주로 소인수분해 문제(예: RSA) 또는 타원 곡선 알고리즘(ECC)의 복잡성에 기초하여 설계됩니다.

2. Python에서 RSA 키 쌍 생성 및 서명 생성

cryptography 라이브러리는 Python에서 공개 키 기반 암호화를 다루기 위한 인기 있는 라이브러리입니다. 이를 이용해 RSA 키를 생성하고 서명을 만드는 방법을 설명하겠습니다.

2.1. cryptography 라이브러리 설치

먼저, cryptography 라이브러리를 설치합니다.

pip install cryptography

2.2. RSA 키 쌍 생성

RSA 키 쌍을 생성하려면 개인 키와 공개 키를 생성해야 합니다.

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa

# RSA 키 쌍 생성
private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)

public_key = private_key.public_key()

# 개인 키와 공개 키 생성 완료

2.3. 메시지에 서명 생성

이제 생성된 개인 키로 메시지에 서명을 추가합니다. 서명은 메시지의 해시 값에 대해 개인 키로 암호화한 것입니다.

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

# 서명할 메시지
message = b"A message I want to sign"

# 개인 키로 서명 생성
signature = private_key.sign(
    message,
    padding.PSS(
        mgf=padding.MGF1(hashes.SHA256()),
        salt_length=padding.PSS.MAX_LENGTH
    ),
    hashes.SHA256()
)

print("Signature:", signature)

위 코드에서 메시지의 해시 값은 SHA-256 알고리즘을 사용하여 계산되며, PSS 패딩 방식을 통해 서명이 안전하게 처리됩니다.

2.4. 서명 검증

서명이 올바른지, 즉 메시지가 변조되지 않았는지 확인하기 위해 공개 키로 서명을 검증할 수 있습니다.

# 공개 키로 서명 검증
try:
    public_key.verify(
        signature,
        message,
        padding.PSS(
            mgf=padding.MGF1(hashes.SHA256()),
            salt_length=padding.PSS.MAX_LENGTH
        ),
        hashes.SHA256()
    )
    print("서명 검증 성공: 메시지가 변경되지 않았습니다.")
except Exception as e:
    print("서명 검증 실패:", e)

3. 공개 키와 개인 키 저장 및 로드

생성된 공개 키와 개인 키를 파일에 저장하고, 나중에 다시 불러올 수 있습니다.

3.1. 개인 키 저장

from cryptography.hazmat.primitives import serialization

# PEM 형식으로 개인 키를 저장
with open("private_key.pem", "wb") as key_file:
    key_file.write(
        private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption()  # 암호화를 원하면 비밀번호 설정 가능
        )
    )

3.2. 공개 키 저장

# PEM 형식으로 공개 키 저장
with open("public_key.pem", "wb") as key_file:
    key_file.write(
        public_key.public_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PublicFormat.SubjectPublicKeyInfo
        )
    )

3.3. 저장된 키 로드

저장된 키는 다음과 같이 다시 로드할 수 있습니다.

개인 키 로드

with open("private_key.pem", "rb") as key_file:
    private_key = serialization.load_pem_private_key(
        key_file.read(),
        password=None,
        backend=default_backend()
    )

공개 키 로드

with open("public_key.pem", "rb") as key_file:
    public_key = serialization.load_pem_public_key(
        key_file.read(),
        backend=default_backend()
    )