RSA 공개지수 65537의 의미와 PKCS#8 vs PKCS#1 포맷 함정
RSA 키를 생성해본 사람은 대부분 "65537"이라는 숫자를 한 번쯤 봤을 겁니다. 왜 항상 이 값인지, 그리고 "BEGIN RSA PRIVATE KEY"와 "BEGIN PRIVATE KEY"라는 비슷하게 생긴 두 헤더가 왜 서로 다른 프로그램에서 파싱 오류를 일으키는지, 원리를 짚고 넘어갑니다.
1. 왜 하필 65537인가: 3도 아니고 임의의 큰 소수도 아닌 이유
RSA 공개키는 (n, e) 쌍으로 이루어지고, e가 바로 공개지수입니다. 이론상 e는 조건만 맞으면 어떤 값이든 가능하지만, 실무에서는 거의 항상 65537(2¹⁶+1, 페르마 소수 F4)을 씁니다. 이진수로 표기하면 1000000000000001로, 1인 비트가 딱 2개뿐입니다. 모듈러 거듭제곱 연산은 "제곱 후 곱하기"를 비트마다 반복하는데, 1비트가 적을수록 곱셈 횟수가 줄어 암호화·서명 검증이 빨라집니다. 반대로 e=3처럼 너무 작은 값은 특정 조건에서 개인 키 없이도 평문을 복원할 수 있는 저지수 공격에 취약해집니다. 65537은 이 둘 사이에서 계산 효율과 공격 저항성을 동시에 만족하는 사실상의 업계 표준값입니다.
2. PKCS#1과 PKCS#8: 같은 RSA 키인데 헤더가 다른 이유
개인 키를 PEM으로 내보낼 때 실제로 두 가지 포맷이 존재합니다. PKCS#1은 RSA 전용 포맷으로 "-----BEGIN RSA PRIVATE KEY-----" 헤더를 쓰며, 키 구조 안에 알고리즘 정보가 암묵적으로 RSA라는 것만 담겨 있습니다. PKCS#8은 범용 포맷으로 "-----BEGIN PRIVATE KEY-----" 헤더를 쓰고, 내부에 이 키가 RSA인지 EC인지 알려주는 알고리즘 식별자(AlgorithmIdentifier)를 명시적으로 포함합니다. 즉 PKCS#8은 "이 키가 RSA다"라는 정보를 파일 자체에 내장하고, PKCS#1은 파일 밖(맥락)에서 그것을 알고 있어야 합니다.
| 포맷 | PEM 헤더 | 알고리즘 정보 | 범용성 |
|---|---|---|---|
| PKCS#1 | BEGIN RSA PRIVATE KEY | 암묵적(RSA 전용) | 낮음 |
| PKCS#8 | BEGIN PRIVATE KEY | 명시적 식별자 포함 | 높음(RSA·EC 등 공통) |
3. 왜 파싱이 자주 실패하나: 프로그램마다 기대하는 포맷이 다름
어떤 라이브러리는 PKCS#8만 읽도록 작성되어 있고, 어떤 레거시 도구는 PKCS#1만 인식합니다. OpenSSL 자체도 버전에 따라 기본 출력 포맷이 다릅니다. genrsa 명령은 전통적으로 PKCS#1을, genpkey 명령은 PKCS#8을 출력합니다. 그래서 "분명히 RSA 키를 만들었는데 다른 프로그램에서 못 읽는다"는 문제는 대부분 알고리즘 자체의 오류가 아니라 두 포맷 사이의 헤더·구조 불일치 때문입니다. RSA 키 생성기는 Web Crypto API의 exportKey('pkcs8', ...)를 사용해 개인 키를 항상 PKCS#8로, 공개키는 X.509 SPKI(SubjectPublicKeyInfo)로 내보내므로 최신 도구 대부분과 호환됩니다.
4. 포맷을 서로 변환해야 할 때
PKCS#1로 받은 키를 PKCS#8이 필요한 프로그램에 넣어야 한다면 openssl pkcs8 -topk8 -nocrypt -in pkcs1.pem -out pkcs8.pem 명령으로 변환할 수 있습니다. 반대로 PKCS#8을 PKCS#1로 되돌리려면 openssl rsa -in pkcs8.pem -out pkcs1.pem을 사용합니다. 어느 포맷인지 헷갈릴 때는 파일을 열어 헤더 한 줄만 확인하면 됩니다 — "RSA PRIVATE KEY"가 붙어 있으면 PKCS#1, 없으면 PKCS#8입니다.
5. CSR·SSH 등 인접 작업에서의 연결점
공개지수와 포맷 문제는 RSA 키를 다루는 다른 작업에도 그대로 이어집니다. SSL 인증서를 발급하기 전 CSR을 만들 때도 내부적으로 같은 RSA 키 쌍이 쓰이며, CSR 생성기에서 만든 개인 키 역시 결국 PKCS#1/PKCS#8 포맷 이슈에서 자유롭지 않습니다. SSH 접속용 키는 또 다른 OpenSSH 전용 포맷을 쓰므로 SSH 키 생성기로 별도 생성하는 것이 안전합니다.
자주 묻는 질문
Q. 공개지수를 65537이 아닌 다른 값으로 바꿀 수 있나요?
기술적으로는 가능하지만 대부분의 도구와 라이브러리가 65537을 표준으로 고정해두고 있습니다. 임의로 바꾸면 상호 호환성 문제와 보안 검토 부담만 늘어나므로 특별한 이유가 없다면 권장하지 않습니다.
Q. 공개키에도 PKCS#1/PKCS#8 구분이 있나요?
공개키는 보통 X.509 SubjectPublicKeyInfo(SPKI) 포맷 하나로 통일되어 있어 개인 키만큼 포맷 혼란이 크지 않습니다. 혼동이 생기는 쪽은 대부분 개인 키입니다.
Q. 어떤 포맷인지 명령어 없이 눈으로 구분할 수 있나요?
네. PEM 파일을 열어 첫 줄이 "-----BEGIN RSA PRIVATE KEY-----"면 PKCS#1, "-----BEGIN PRIVATE KEY-----"면 PKCS#8입니다.
Q. 브라우저에서 생성한 키를 서버 프로그램에서 바로 써도 되나요?
PKCS#8/SPKI PEM 형식은 OpenSSL 3.x를 포함한 대부분의 최신 서버 도구와 호환됩니다. 다만 아주 오래된 레거시 시스템이라면 PKCS#1 변환이 필요할 수 있습니다.