RSA 공개키 암호화의 원리와 안전한 운영
RSA의 키 생성과 암호화·복호화 원리, 디지털 서명과 PKI 활용, 구현 및 운영 시 보안 고려사항을 정리한다.
2026-08-14 · 최초 발행 2025-06-08
RSA는 1977년 Ron Rivest, Adi Shamir, Leonard Adleman이 개발한 비대칭 암호화 알고리즘이다. 큰 수의 소인수분해가 어렵다는 수학적 성질을 기반으로, 전자상거래·디지털 서명·보안 통신 등 인터넷 보안의 여러 지점에서 쓰여 왔다.
공개키와 개인키를 만드는 수학적 구조
RSA의 출발점은 두 개의 큰 소수다. 이 소수의 곱으로 만든 합성수는 알 수 있지만, 그 값을 다시 두 소수로 분해하기는 계산적으로 어렵다는 점을 이용한다.
암호화와 복호화에는 모듈러 연산이 사용된다. RSA의 수학적 증명에서는 오일러 정리도 중요하다. φ(n)은 n과 서로소인 1부터 n-1까지의 정수 개수를 뜻하는 오일러 토션트 함수다.
키는 다음 관계를 만족하도록 생성한다.
- 두 개의 큰 소수 p, q를 선택한다. 일반적으로 수백 또는 수천 비트 크기의 소수를 사용한다.
- n = p × q를 계산한다.
- φ(n) = (p-1) × (q-1)을 계산한다.
- 1 < e < φ(n)이면서 e와 φ(n)이 서로소인 공개키 e를 고른다.
- e × d ≡ 1 (mod φ(n))을 만족하는 개인키 d를 구한다.
공개키는 (e, n), 개인키는 (d, n)으로 구성된다. n은 두 키에 포함되지만 d는 외부에 노출되어서는 안 된다.
평문을 암호문으로 바꾸고 되돌리는 과정
송신자는 평문 M을 숫자로 변환한다. 이때 일반적으로 M < n이어야 한다. 공개키를 사용해 C = M^e mod n을 계산하면 암호문 C를 얻는다.
수신자는 개인키로 M = C^d mod n을 계산해 원본 평문을 복원한다. 공개키만으로는 암호화할 수 있지만, 복호화에는 개인키가 필요하다.
RSA의 보안은 수학만으로 결정되지 않는다
RSA는 충분히 큰 수의 소인수분해가 현실적인 시간 안에 어렵다는 전제 위에서 안전성을 확보한다. 현재 권장되는 RSA 키 길이는 최소 2048비트 이상이다.
다만 안전성은 키 길이만으로 보장되지 않는다. 암호화 과정의 시간, 전력 소비, 전자기파를 분석해 키 정보를 얻는 사이드 채널 공격이 가능하며, 잘못된 구현과 예측 가능한 난수도 키 생성의 안전성을 크게 떨어뜨릴 수 있다. 블라인드 서명 과정의 취약점을 노리는 공격도 고려 대상이다.
Shor 알고리즘을 사용하는 양자 컴퓨터는 RSA를 효율적으로 공격할 수 있다. 실용적인 양자 컴퓨터는 아직 개발 중이지만, 장기적인 암호 체계 설계에서는 이 위협을 분리해서 볼 수 없다.
인증서와 서명 체계에서의 활용
RSA는 웹 브라우저와 서버가 보안 통신을 시작하는 TLS/SSL 프로토콜의 초기 핸드셰이크에서 대칭키 교환에 사용된다. HTTPS로 보호되는 온라인 뱅킹과 전자상거래 사이트가 그 예다.
전자 문서의 무결성과 출처를 확인하는 디지털 서명에서도 RSA를 활용한다. 해시 함수와 함께 사용해 서명 체계를 구성하며, 전자계약·소프트웨어 패키지 서명·디지털 인증서가 대표적인 사용처다.
PKI(Public Key Infrastructure)에서는 인증기관(CA)이 발행하는 디지털 인증서의 핵심 기술로 쓰인다. 신원을 확인하고 암호화 키를 관리하는 기반이며, X.509 인증서·스마트카드·VPN 연결에 적용된다.
구현 예제를 읽을 때 봐야 할 관계
아래 예제는 소수 생성, 모듈러 역원 계산, 키 쌍 생성, 문자열 암호화와 복호화의 관계를 보여 준다.
import random
from math import gcd
# 소수 판별 함수
def is_prime(n, k=5):
if n <= 1:
return False
if n <= 3:
return True
# Miller-Rabin 소수 판별법
def miller_rabin(n, a):
d = n - 1
while d % 2 == 0:
d //= 2
x = pow(a, d, n)
if x == 1 or x == n - 1:
return True
while d != n - 1:
x = (x * x) % n
d *= 2
if x == 1:
return False
if x == n - 1:
return True
return False
# k번의 테스트 진행
for _ in range(k):
a = random.randint(2, n - 2)
if not miller_rabin(n, a):
return False
return True
# 랜덤 소수 생성
def generate_prime(bits):
while True:
p = random.getrandbits(bits)
if is_prime(p):
return p
# 확장 유클리드 알고리즘으로 모듈러 역원 찾기
def mod_inverse(e, phi):
def extended_gcd(a, b):
if a == 0:
return b, 0, 1
else:
gcd, x, y = extended_gcd(b % a, a)
return gcd, y - (b // a) * x, x
gcd, x, y = extended_gcd(e, phi)
if gcd != 1:
raise Exception('모듈러 역원이 존재하지 않습니다')
else:
return x % phi
# RSA 키 생성
def generate_keypair(bits):
p = generate_prime(bits // 2)
q = generate_prime(bits // 2)
n = p * q
phi = (p - 1) * (q - 1)
# 공개키 e 선택
e = 65537 # 일반적으로 사용되는 값
# 개인키 d 계산
d = mod_inverse(e, phi)
return ((e, n), (d, n))
# 암호화
def encrypt(public_key, plaintext):
e, n = public_key
# 문자를 숫자로 변환하여 암호화
cipher = [pow(ord(char), e, n) for char in plaintext]
return cipher
# 복호화
def decrypt(private_key, ciphertext):
d, n = private_key
# 암호문을 복호화하여 문자로 변환
plain = [chr(pow(char, d, n)) for char in ciphertext]
return ''.join(plain)
# 사용 예
public_key, private_key = generate_keypair(1024)
message = "RSA 암호화 테스트"
encrypted = encrypt(public_key, message)
decrypted = decrypt(private_key, encrypted)
print(f"원본 메시지: {message}")
print(f"암호화된 메시지: {encrypted}")
print(f"복호화된 메시지: {decrypted}")
대칭키 암호와 양자 시대의 대안
RSA는 대칭키 암호화보다 연산 속도가 느리고, 대용량 데이터를 직접 암호화하기에는 비효율적이다. 실제 구현에서는 RSA로 대칭키를 안전하게 교환한 뒤 AES 등의 대칭키 알고리즘을 사용한다.
더 짧은 키 길이로 동등한 보안 수준을 제공하는 타원곡선 암호(ECC)는 RSA의 대안이다. 모바일 기기처럼 자원이 제한된 환경에서 효율적이며, 256비트 ECC 키는 3072비트 RSA 키와 유사한 보안 수준을 제공한다.
포스트 양자 암호도 함께 개발되고 있다. 격자 기반 암호, 해시 기반 서명, 다변수 다항식 기반 암호가 대안으로 연구되고 있으며, NIST는 포스트 양자 암호 표준화를 진행 중이다.
구현과 운영에서 지켜야 할 기준
키 길이는 최소 2048비트 이상을 사용하고, 키 생성에는 안전한 난수 생성기(CSPRNG)를 적용해야 한다. 패딩 방식은 PKCS#1 v2.0 이상을 사용한다.
구현 단계에서는 OpenSSL, Bouncy Castle과 같이 검증된 암호화 라이브러리를 사용하고 PKCS#1, X.509 등의 표준을 준수해야 한다. 보안 업데이트도 정기적으로 적용한다.
운영 환경에서는 개인키를 안전하게 보관해야 하며 HSM 사용이 권장된다. 키 교체 정책을 수립하고 이행하는 일, 사이드 채널 공격에 대응하는 방안을 구현하는 일도 RSA 운용의 일부다.
RSA는 소인수분해 난이도와 비대칭 암호화의 장점을 결합해 오랫동안 인터넷 보안의 중추 역할을 해왔다. 양자 컴퓨팅은 장기적 안전성에 대한 과제를 남기지만, 적절한 구현과 운영 지침을 적용하면 RSA는 여전히 여러 응용 분야에서 사용할 수 있다.