모바일 및 데스크톱 애플리케이션의 인증서 고정
HPKP와 TrustKit 방식의 고정을 구현하고 고정 방식이 초래하는 운영상의 위험을 이해합니다.
모바일 및 데스크톱 애플리케이션의 인증서 고정은(는) CoddyKit의 무료 Cryptology Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Cryptology Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Cryptology Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
인증서 고정이 필요한 이유
표준 TLS는 OS에 사전 설치된 약 150개의 루트 CA 중 어느 하나가 서명한 인증서든 신뢰합니다. 루트 CA 하나라도 침해되거나 강요를 받으면 공격자가 어떤 도메인에 대해서든 인증서를 발급받아 TLS 트래픽을 가로챌 수 있습니다. 인증서 고정은 어떤 CA가 서명했는지와 관계없이 특정 인증서나 공개 키만 신뢰하도록 제한합니다. 인증서가 고정된 애플리케이션은 서버가 정확히 예상한 인증서나 키를 제시하지 않으면 해당 서버에 연결하지 않습니다. 사용자가 네트워크 트래픽을 직접 확인할 수 없고 기업 MDM 솔루션이 기업용 CA 루트를 설치할 수 있는 모바일 앱에서 이 보호 기능은 특히 중요합니다.
고정 유형: 인증서, 공개 키, SPKI
고정에는 세 가지 세분화 수준이 있습니다. (1) 전체 인증서 고정 — DER로 인코딩된 정확한 인증서가 일치해야 합니다. 인증서를 갱신할 때마다 중단되므로 가장 취약합니다. (2) 공개 키 고정 — SubjectPublicKeyInfo(SPKI) 바이트만 비교합니다. 동일한 키 쌍을 유지하면 인증서를 갱신해도 계속 사용할 수 있습니다. (3) SPKI 해시 — 원시 키 대신 SHA-256(SPKI)을 저장합니다. 이는 HTTP Public Key Pinning(HPKP)과 Android 네트워크 보안 구성에서 사용하는 방식입니다. 공개 키 또는 SPKI 고정을 권장합니다. 이 방식은 CA 교체와 인증서 갱신을 허용하면서도 다른 키 쌍을 사용하는 MITM을 계속 탐지합니다.
Android 네트워크 보안 구성
Android(API 24 이상)는 네트워크 보안 구성 XML을 통해 선언적인 고정 기능을 제공합니다. res/xml/network_security_config.xml 파일에서 도메인별 고정을 지정합니다. pin-set에 digest="SHA-256"과 base64로 인코딩된 SPKI 해시를 설정합니다. 앱은 AndroidManifest.xml에서 android:networkSecurityConfig를 통해 이 파일을 참조합니다. Android는 표준 HttpsURLConnection과 OkHttp(플랫폼 신뢰 관리자를 사용하는 경우)를 통해 이루어지는 모든 HTTP 연결에 고정을 적용합니다. 기본 키가 침해되었을 때 연결이 완전히 차단되는 것을 방지하려면 pin-set에 하나 이상의 백업 고정(다른 키 또는 CA 고정)이 필요합니다. 고정 만료(expiration 속성)를 설정하면 고정이 오래되어 사용할 수 없게 되기 전에 앱을 업데이트하도록 강제할 수 있습니다.
iOS / macOS 인증서 고정
iOS 앱은 NSURLSession 대리자에서 고정을 구현합니다. URLSession(_:didReceive:completionHandler:) 대리자 메서드는 서버 신뢰 객체를 받습니다. 앱은 SecTrustEvaluateWithError를 호출해 인증서 체인을 검증한 다음, SecTrustGetCertificateAtIndex(trust, 0)로 리프 인증서를 추출하고 SPKI 바이트를 내보냅니다. 그런 다음 SHA-256으로 해시한 결과를 저장된 고정 값과 비교합니다. TrustKit(오픈 소스 라이브러리)는 이 방식을 구성 기반 고정으로 감싸며 여러 고정 값, 하위 도메인 일치, 보고 전용 모드를 지원합니다. Apple의 앱 전송 보안(ATS)은 고정과 별개입니다. ATS는 TLS 버전의 최솟값을 강제하지만 키를 고정하지는 않습니다.
HPKP: HTTP Public Key Pinning(사용 중단됨)
HTTP Public Key Pinning(HPKP, RFC 7469)은 HTTP 응답 헤더를 통해 웹 브라우저에 고정 기능을 추가하려고 했습니다. 헤더 형식은 Public-Key-Pins: pin-sha256="base64=="; max-age=5184000; includeSubDomains였습니다. 브라우저는 max-age 기간 동안 고정 값을 기억하고 일치하지 않는 키에 대한 연결을 거부합니다. HPKP는 치명적인 장애 때문에 Chrome에서 2017년에 사용 중단되었고 2019년에 제거되었습니다. 한 번의 잘못된 구성이나 키 손실만으로도 복구 방법 없이 사용자가 웹사이트에 영구적으로 접근하지 못할 수 있었기 때문입니다. 현재 HPKP는 웹 브라우저에서 사실상 폐기되었지만, 앱 업데이트로 새 고정 값을 배포할 수 있는 모바일 앱에서는 애플리케이션 수준의 고정을 계속 사용할 수 있습니다.
OkHttp에서의 고정
OkHttp(Android에서 널리 사용됨)는 CertificatePinner를 통해 고정을 지원합니다: CertificatePinner.Builder().add("api.example.com", "sha256/AAAA...==", "sha256/BBBB...==").build(). 두 번째 고정 값은 백업입니다. OkHttp는 서버 인증서 체인에 있는 인증서(리프, 중간 또는 루트) 중 하나 이상이 고정 값과 일치하는지 확인합니다. 따라서 중간 CA에 고정하여 리프 인증서 갱신에도 대응하거나, 루트 CA에 고정하여 중간 인증서 갱신에도 대응할 수 있습니다. OkHttp는 서버의 실제 SPKI 해시를 나열하는 유용한 메시지와 함께 SSLPeerUnverifiedException을 발생시키므로 개발 중 고정 값을 쉽게 추출할 수 있습니다.
고정 우회: 공격자 기법
고정은 트래픽 가로채기의 난도를 높이지만 절대적인 방어 수단은 아닙니다. 모바일에서 흔히 사용되는 우회 기법은 다음과 같습니다. (1) Frida 후킹 — 앱 프로세스에 JavaScript를 주입해 고정 확인 메서드를 후킹하고 무조건 true를 반환하게 합니다. (2) SSLUnpinning 도구 — 일반적인 고정 라이브러리(TrustKit, OkHttp, 네이티브 SecTrust)를 대상으로 하는 Frida/Objection 자동화 스크립트입니다. (3) 사용자 지정 ROM — 기기를 루팅하고 TLS 스택을 수정합니다. (4) 재패키징 — APK를 디컴파일하고 고정 구성을 수정한 다음 새 인증서로 다시 패키징합니다. (5) 메모리 패치 — 실행 중 확인 바이트코드를 수정합니다. 대응 방법으로는 루트/탈옥 탐지, 코드 난독화, 무결성 확인(SafetyNet/App Attest)이 있습니다.
백업 고정 값과 재해 복구
인증서 고정의 가장 큰 운영 위험은 자체적인 접근 차단입니다. 운영 키를 잃거나 인증서가 만료되었는데 백업을 사용할 수 없다면 앱 업데이트가 배포될 때까지(며칠에서 몇 주) 사용자가 접근하지 못합니다. 모범 사례는 다음과 같습니다. (1) 현재 키와 오프라인(HSM 또는 망분리 환경)에 보관한 사전 생성 백업 키 등 최소 두 개의 키를 항상 고정합니다. (2) 고정 만료일을 설정하고 만료 전에 앱 업데이트를 배포합니다. (3) 적용하기 전에 보고 전용 모드로 고정 실패를 모니터링합니다. (4) 고정 갱신 사고에 대비해 긴급 앱 업데이트 파이프라인(신속 심사)을 유지합니다. (5) 리프 인증서가 아니라 중간 CA 수준에서 고정하여 앱 업데이트 없이도 리프 인증서를 갱신할 수 있도록 합니다.
데스크톱 애플리케이션 고정
Electron, Qt 또는 네이티브 코드로 작성된 데스크톱 애플리케이션은 TLS 스택 API를 사용해 고정을 구현할 수 있습니다. Electron 앱은 app.on("certificate-error") 이벤트와 session.setCertificateVerifyProc()를 사용해 사용자 지정 검증을 구현합니다. Qt 네트워크 코드는 사용자 지정 검증 콜백과 함께 QSslSocket을 사용합니다. .NET 애플리케이션은 ServicePointManager.ServerCertificateValidationCallback을 사용합니다. 네이티브 Windows 앱은 수동 인증서 검사를 수행하는 WinHTTP를 사용합니다. 데스크톱 애플리케이션에는 추가 과제가 있습니다. 기업 프록시를 통한 OS 수준의 TLS 가로채기가 흔하고 사용자는 프록시 기능이 작동하기를 기대할 수 있으므로, 고정을 특정 엔드포인트에만 적용할지 정책을 결정해야 합니다.
CI/CD 및 자동화된 테스트에서의 고정
인증서 고정은 자동화된 테스트와 CI/CD 파이프라인을 복잡하게 만듭니다. 스테이징 서버에 실제 HTTPS 호출을 수행하는 통합 테스트에서는 SPKI 해시가 테스트 구성에 고정된 테스트 인증서를 사용해야 합니다. 접근 방법은 다음과 같습니다. (1) 빌드 변형 — 디버그/스테이징 빌드에는 스테이징 서버 고정 값을 포함하고, 릴리스 빌드에는 운영 환경 고정 값을 포함합니다. (2) 네트워크 보안 구성 재정의 — Android에서는 디버그 전용 고정 구성을 허용합니다. (3) 모의 서버 — TLS 전에 HTTP 클라이언트 계층에서 가로채 고정을 완전히 우회합니다. (4) CI용 자체 서명 CA — 테스트 빌드에서만 신뢰하는 CI CA로 테스트 인증서를 발급합니다. 운영 환경에서 고정이 비활성화된 빌드를 절대 배포해서는 안 됩니다.
고정을 위한 양자 이후 암호 고려 사항
인증서 고정 값은 일반적으로 RSA 또는 EC 공개 키의 해시입니다. 양자 이후 암호로의 마이그레이션이 시작되면 서버는 ML-DSA(CRYSTALS-Dilithium) 또는 하이브리드 키로 전환합니다. 키 유형과 인코딩이 변경되므로 고정된 SPKI 해시도 변경됩니다. 리프 인증서나 공개 키를 고정하는 앱은 다음과 같이 조율된 업데이트가 필요합니다. (1) 서버를 마이그레이션하기 전에 양자 이후 SPKI 해시를 백업 고정 값으로 포함한 새 앱 버전을 배포합니다. (2) 서버 마이그레이션을 완료합니다. (3) 이전의 고전 암호 고정 값을 제거하는 업데이트를 배포합니다. 전환 기간에는 세심한 조율이 필요합니다. 중간 CA 또는 루트 CA를 고정하는 앱은 영향을 덜 받습니다. 변경되는 것은 CA의 키뿐이며, 반드시 리프 인증서와 같은 일정으로 변경될 필요는 없기 때문입니다.
인증서 고정 퀴즈
전체 인증서를 고정하는 것보다 SubjectPublicKeyInfo(SPKI) 해시를 고정하는 것이 선호되는 이유는 무엇인가요?
인증서 고정 복습
인증서 고정은 TLS 신뢰를 특정 인증서나 공개 키로 제한하여 CA 손상과 MITM으로부터 보호합니다. SPKI 해시 고정(SubjectPublicKeyInfo의 SHA-256 해시)은 갱신에 더 잘 대응할 수 있으므로 전체 인증서 고정보다 선호됩니다. Android에서는 Network Security Config XML을 사용하고, iOS에서는 SecTrust API와 함께 URLSession 대리자를 사용하며, OkHttp는 CertificatePinner를 지원합니다. 연결이 스스로 잠기는 상황을 방지하려면 항상 백업 핀을 포함해야 합니다. HPKP(브라우저 HTTP 헤더)는 더 이상 사용되지 않습니다. Frida 후크와 ROM 수정으로 고정을 우회할 수 있습니다. 양자 내성 키로 마이그레이션하려면 SPKI 해시를 업데이트할 수 있도록 앱을 조율하여 업데이트해야 합니다.
자주 묻는 질문
“모바일 및 데스크톱 애플리케이션의 인증서 고정” 강의는 무료인가요?
네 — “모바일 및 데스크톱 애플리케이션의 인증서 고정” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Cryptology Academy 강의 전체를 잠금 해제할 수 있습니다. Cryptology Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“모바일 및 데스크톱 애플리케이션의 인증서 고정”에서 뭘 배우나요?
HPKP와 TrustKit 방식의 고정을 구현하고 고정 방식이 초래하는 운영상의 위험을 이해합니다. 브라우저에서 직접 실행하는 실습 코드로 Cryptology Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Cryptology Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Cryptology Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“모바일 및 데스크톱 애플리케이션의 인증서 고정” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Cryptology Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Cryptology Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- TLS 1.3: 0-RTT, 조기 데이터 및 세션 재개
- 상호 TLS (mTLS) 구현 패턴
- 모바일 및 데스크톱 애플리케이션의 인증서 고정
- TLS 성능: QUIC와 HTTP/3