728x90

X.509 인증서란

 

X.509 인증서는 공개키 기반 구조(PKI, Public Key Infrastructure)에서 사용되는 표준화된 인증서 형식입니다. 주로 SSL/TLS, 전자서명, 암호화 이메일, VPN 등에서 신원 확인데이터 암호화를 위해 사용됩니다.

핵심 목적은:

  • 공개키가 특정 엔티티(예: 사용자, 서버, 조직)에 속함을 증명
  • 제3자(CA, 인증기관)를 통해 그 신뢰성을 보증

 

즉, 클라이언트가 서버에 연결할 때, 서버가 제공하는 X.509 인증서를 통해 서버의 신원을 확인하고, 교환하는 공개키가 신뢰할 수 있는지를 검증합니다.

 

X.509 인증서의 구조

인증서는 ASN.1 (Abstract Syntax Notation One)로 정의되고 DER 또는 PEM 형식으로 인코딩됩니다. 주요 필드는 아래와 같습니다:

 

1. 기본 필드

필드명 설명
Version 인증서 버전(v1, v2, v3)
현재 v3가 표준
Serial Number CA가 발생한 고유 인증서 일련번호
Signature Algorithm 인증서 서명에 사용된 알고리즘
(예 : SHA256withRSA)
Issuer 인증서를 발행한 기관(CA)이름
Validity Period 인증서의 유효기간
(Not Before ~ Not After)
Subject 인증서 소유자
(예: 도메인, 사용자, 조직)
Subject Public Key Info 공개키 정보 및 알고리즘
(예: RSA, ECDSA)

 


2. 서명 필드

필드명 설명
Signature CA가 인증서 내용에 대해 생성한 디지털 서명
Signature Algorithm 서명 생성에 사용된 알고리즘(위와 동일)



이 서명을 통해 클라이언트는 인증서의 위조 여부를 검증할 수 있습니다.

 

3.  확장 필드 (v3 Extensions)


버전 3에서 확장 필드를 통해 다양한 기능이 추가됩니다:

 

확장 필드 설명
Key Usage 공개키 사용 목적
(예 : Digital Signature, Key Encipherment)
Extended Key Usage 추가용도
(예: TLS 서버 인증, 클라이언트인증, 코드 서명)
Subject Alternative Name(SAN) 추가 식별자
(예: 여러 도메인 이름, 이메일, IP 주소)
Basic Constraints CA 여부(CA인증서인지 여부와 경로 길이 제한)
CRL Distribution Point 인증서 폐기 목록(CRL)위치
Authority Key Identifier 상위 CA의 키 식별자
Subject Key Identifier 이 인증서의 키 식별자

 

CRL(Certificate Revocation List)란?
CRL은 더 이상 유효하지 않은 인증서 목록입니다.
CA(인증기관)가 발급한 인증서 중에서 특정 이유로 폐기(revoke)된 것들을 기록하고,
신뢰할 수 없는 인증서를 식별하기 위해 배포하는 리스트입니다.

 

 

인증서 예시 (PEM 형식)

-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKP3...
-----END CERTIFICATE-----
이 파일을 base64로 디코딩하면 ASN.1로 인코딩된 바이너리 데이터가 나오고, 각 필드가 순서대로 들어 있습니다.

 

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            12:34:56:78:9a:bc:de:f0:12:34:56:78:9a:bc:de:f0
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Example CA, CN=Example Root CA
        Validity
            Not Before: May  1 00:00:00 2025 GMT
            Not After : May  1 23:59:59 2026 GMT
        Subject: C=US, O=Example Corp, CN=www.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:b1:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:
                    cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67:89:
                    ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67:
                    89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:
                    ...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Subject Alternative Name:
                DNS:www.example.com, DNS:example.com
            Authority Information Access:
                OCSP - URI:http://ocsp.exampleca.com
                CA Issuers - URI:http://crt.exampleca.com/ExampleCA.crt
            X509v3 Authority Key Identifier:
                keyid:12:34:56:78:9A:BC:DE:F0:12:34:56:78:9A:BC:DE:F0
            X509v3 Subject Key Identifier:
                12:34:56:78:9A:BC:DE:F0:12:34:56:78:9A:BC:DE:F0
    Signature Algorithm: sha256WithRSAEncryption
         a1:b2:c3:d4:e5:f6:01:23:45:67:89:ab:cd:ef:01:23:
         45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:
         ...

 

PEM과 DER 형식 인증서의 차이

구분 PEM DER
형식 Base64로 인코딩된 텍스트 + 헤더/푸터 포함 바이너리(순수 ASN.1 인코딩)
확장자 .pem, .crt, .cer .der,  .cer
사용 예 주로 웹서버, 텍스트 기반 시스템 주로 Windows, Java 시스템, 바이너리 처리
내용 Base64 디코딩하면 DER 내용과 동일 DER 바이너리 자체

 


X.509 신뢰 체계

  • 루트 CA → 중간 CA → 최종 엔티티 인증서로 이어지는 체인이 있습니다.
  • 클라이언트(예: 브라우저)는 루트 CA의 공개키를 신뢰하고, 그로부터 서명된 하위 인증서를 따라 내려오며 최종 서버 인증서까지 신뢰성을 검증합니다.

 

 

OpenSSL을 사용한 인증서 생성 방법

 

1. 개인키 생성

openssl genrsa -out server.key 2048

 

2. CSR(Certificate Signing Request) 생성

openssl req -new -key server.key -out server.csr

 

실행하면 여러 질문이 발생합니다.

  • Country Name(국가코드, 예: KR)
  • State or Province Name(도/시)
  • Locality Name(구/군)
  • Organization Name(회사명)
  • Organizational Unit Name(부서)
  • Common Name(도메인 명, 예: www.example.com)
  • Email Address

 

3. 인증서 발급

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

 

3-1 (선택) CA를 통한 서명

  • CA용 개인 키 및 자체 서명 루트 인증서 생성
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt

 

  • CA가 CSR을 서명
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256

 

 

4. 인증서 확인(PEM)

openssl x509 -in server.crt -outform DER -out server.der

 

4-1 DER 인증서인 경우

openssl x509 -in server.der -inform DER -text -noout
728x90
728x90

 

OpenSSL Provider란?

기존 OpenSSL 1.1.x까지는 암호 알고리즘이 libcrypto 안에 하드코딩되어 있었습니다.
하지만 OpenSSL 3.0부터는 이런 암호 알고리즘 구현을 플러그인(Provider) 형태로 분리했습니다.

즉, Provider는 OpenSSL에서 사용할 수 있는 암호 알고리즘, 키 관리, 서명, 해시 등 암호 서비스들의 집합입니다.
OpenSSL 라이브러리 본체는 이 Provider들로부터 필요한 기능을 가져와서 실행합니다.

 

 왜 Provider를 도입했나?

  • 유연성
    새로운 알고리즘이나 하드웨어 가속 기능을 추가할 때 OpenSSL을 직접 수정하거나 재컴파일할 필요 없이, 별도 Provider만 추가하면 됩니다.
  • 정책 분리
    예: FIPS 인증된 알고리즘만 사용해야 할 경우, FIPS Provider만 로드하면 됩니다. 반대로 개발용에선 Default Provider를 쓰면 됩니다.
  • 사용자 정의
    개발자가 직접 자신만의 Provider를 작성해 OpenSSL에 플러그인처럼 붙일 수 있습니다.

 

OpenSSL 기본 제공 Provider 종류

OpenSSL 3.0 설치 시 기본으로 제공되는 Provider들은 다음과 같습니다:

Provider 이름 설명
default 대부분의 표준 알고리즘 (RSA, AES, SHA 등) 포함
fips FIPS 140-2 인증용 알고리즘 제공 (엄격한 보안 요구사항에 맞춤)
legacy 오래되었거나 약한 보안의 알고리즘 제공 (MD5, RC4 등)
null 어떤 암호 기능도 제공하지 않는 빈 Provider (주로 테스트용)

 

Provider의 동작 방식

OpenSSL은 실행 시 또는 설정 파일 (openssl.cnf)에서 로드할 Provider를 지정합니다.

  • 특정 알고리즘 요청 → OpenSSL은 등록된 Provider 목록을 탐색 → 해당 알고리즘을 제공하는 Provider에서 구현을 가져옴
  • 따라서 어떤 Provider를 로드하느냐에 따라 OpenSSL의 기능과 보안 수준이 달라질 수 있습니다.

 

간단한 예: Provider 사용

# FIPS Provider 로드 예제
export OPENSSL_MODULES=/usr/local/lib/ossl-modules
openssl list -providers

# 특정 Provider를 명시적으로 로드하는 코드 예제 (C)
OSSL_PROVIDER *provider = OSSL_PROVIDER_load(ctx, "fips");
if (provider == NULL) {
    fprintf(stderr, "FIPS provider load failed\n");
}

 

 

외부 Provider 예시

1. OpenSSL FIPS Provider (OpenSSL 공식)

  • OpenSSL 팀이 직접 제공하는 FIPS 140-2 인증용 Provider
  • 기존에는 별도 FIPS 모듈로 제공되었지만, 3.x부터는 Provider 형태로 통합됨.

2. Open Quantum Safe (OQS) Provider

  • 양자내성암호(Post-Quantum Cryptography) 알고리즘을 OpenSSL에서 쓸 수 있게 해주는 Provider
  • https://openquantumsafe.org
  • Dilithium, Kyber 등 NIST PQC 최종 후보 알고리즘을 OpenSSL에서 바로 실험할 수 있도록 지원.

3. SoftHSM + PKCS#11 Provider

  • 하드웨어 보안 모듈(HSM)이나 소프트웨어 HSM에서 제공하는 PKCS#11 인터페이스와 연결되는 Provider
  • 예: OpenSC 프로젝트, SoftHSM 등과 연동해 키 관리.

4. Intel QAT (QuickAssist) Provider

  • Intel QAT 하드웨어 가속 기능을 OpenSSL에서 사용하도록 만든 Provider
  • AES, RSA, ECDSA 등 연산을 QAT 장치로 오프로드.

5. NVIDIA GPU Provider (실험적)

  • NVIDIA GPU를 이용해 OpenSSL 암호 연산을 가속하는 Provider (주로 연구용, 아직 널리 사용되지는 않음).

 

 

커스텀 Provider 구현 방법

 

커스텀 Provider의 기본 구성

커스텀 Provider를 만들려면 크게 다음 요소가 필요합니다:

1. Provider 엔트리 포인트
→ OpenSSL이 이 모듈을 로드할 때 호출할 OSSL_provider_init() 함수를 구현해야 합니다.

int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
                       const OSSL_DISPATCH *in,
                       const OSSL_DISPATCH **out,
                       void **provctx);

 

이 함수는:

  • OpenSSL 코어 핸들 handle과
  • Provider가 코어에 제공할 함수 목록 out을 세팅하고
  • Provider 내부 상태를 담은 컨텍스트 provctx를 초기화합니다.

 

2. DISPATCH 테이블
→ Provider가 제공하는 기능들을 OSSL_DISPATCH 배열로 선언합니다.

예:

static const OSSL_DISPATCH my_provider_dispatch_table[] = {
    { OSSL_FUNC_PROVIDER_GETTABLE_PARAMS, (void (*)(void)) my_gettable_params },
    { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void)) my_get_params },
    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void)) my_query_operation },
    { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void)) my_teardown },
    { 0, NULL }
};

 

 

3. 알고리즘 등록
Provider는 my_query_operation() 같은 함수에서 OpenSSL에게
“나는 이 연산(digest, cipher, signature, …)에 대해 이런 알고리즘들을 제공해”라고 알려줍니다.

예:

static const OSSL_ALGORITHM my_digests[] = {
    { "MYHASH", "provider=myprovider", myhash_functions },
    { NULL, NULL, NULL }
};

각 항목은:

  • 알고리즘 이름 (예: MYHASH)
  • 프로퍼티 스트링 (예: provider=myprovider)
  • 함수 테이블 (예: myhash_functions)
    로 구성됩니다.

 

4. 알고리즘 함수 구현
예를 들어 digest를 제공한다면:

  • newctx, freectx, init, update, final, get_params 같은 함수들을 정의해 OSSL_DISPATCH 테이블로 묶습니다.
static const OSSL_DISPATCH myhash_functions[] = {
    { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void)) myhash_newctx },
    { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void)) myhash_update },
    { OSSL_FUNC_DIGEST_FINAL, (void (*)(void)) myhash_final },
    { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void)) myhash_freectx },
    { 0, NULL }
};

 

 

 

개발 흐름 요약

1️⃣ .c 파일로 Provider 코드 작성
2️⃣ OSSL_provider_init()과 필요한 DISPATCH, ALGORITHM 테이블 정의
3️⃣ gcc -shared -fPIC -o myprovider.so myprovider.c -lcrypto로 공유 라이브러리 빌드
4️⃣ OpenSSL에서 환경 변수 또는 openssl.cnf로 모듈 경로 등록
5️⃣ OSSL_PROVIDER_load() 또는 openssl list -digest-algorithms 같은 명령으로 테스트

 

예제 구조

myprovider/
├── Makefile
├── myprovider.c      ← 메인 구현
├── myhash.c          ← 예: custom digest 알고리즘 구현
├── myprovider.so     ← 빌드 후 생성되는 동적 라이브러리

 주의할 점

  •  OpenSSL 내부 API는 잘 문서화되어 있지 않으므로, 기본 제공 Provider 소스 (예: default, legacy)를 참고하는 게 중요합니다.
  •  OpenSSL 버전 간 호환성 문제에 주의해야 합니다 (예: 구조체 변경, DISPATCH 상수 추가 등).
  •  Provider는 OpenSSL Core ↔ Module 형태로 통신하므로, 반드시 명세된 API 범위 내에서만 동작해야 합니다.
728x90

+ Recent posts