Category: 투명하게 파헤치기

  • MD5

    임베디드 장치에 파일을 전송해야하는 일이 생겼다. AI 에이전트에 전송 스크립트를 요청했다. 그랬더니 파일 유효성 검사를 할 것인지, 한다면 MD5를 사용하는게 어떻겠냐고 했다. 나는 MD5가 뭔지는 정확히 몰랐고, 유효성 검사를 할 때 사용한다는 것 정도만 알고 있었다. 그래서 간단히 알아보기로 했다.

    개요

    MD5(Message Digest Algorithm 5)는 임의 데이터를 입력받아 128비트(16바이트) 고정 길이의 해시값을 출력하는 암호화 해시 함수이다. 1991년 Ron Rivest가 MD4를 대체할 목적으로 설계했다.

    핵심 특성

    • 고정 출력: 입력 크기와 무관하게 항상 128비트(32자리 16진수) 출력
    • 단방향성: 해시값으로 원본 데이터를 역산 불가
    • 결정론적: 같은 입력 -> 항상 같은 해시값
    • 눈사태 효과: 입력이 1비트만 바뀌어도 해시값이 완전히 달라짐

    파일 검증에서의 활용

    파일을 다운로드하거나 전송할 때, 파일이 손상/변조되지 않았는지 확인하는 용도로 쓰인다.

    1. 배포자가 MD5 계산값을 공개한다.
    2. 수신자가 파일을 받고 MD5를 계산한 뒤 공개된 값과 비교한다.

    주의할 점

    MD5는 보안 용도로는 취약하다. 현재는 파일 무결성 검사에서만 사용한다.

  • PEM

    PEM은 Privacy Enhanced Mail의 약자다. 원래는 이름 그대로 이메일 보안을 위해 만들어졌다. 하지만 지금은 인증서, 키 그리고 기타 데이터를 저장하고 전송하는 파일 형식으로 널리 쓰인다. 원래 표준은 널리 채택되지 못했지만, 텍스트 인코딩 방식은 매우 대중화되었다고 한다.

    PEM의 형식

    많은 암호화 표준은 ASN.1으로 데이터 구조를 정의한다. 그리고 DER(Distinguished Encoding Rules)를 사용해 직렬화한다. 직렬화된 데이터는 ASCII만 지원하는 이메일 시스템으로 전송하기 어려울 수 있다. 그래서 고안된 것이 PEM이다.

    Base64를 이용해 이진 데이터를 ASCII로 표현할 수 있는 텍스트로 인코딩한다. 그리고 헤더와 푸터를 이용해 해당 데이터 유형을 정의할 수 있다. 예시는 아래와 같다.

    -----BEGIN CERTIFICATE-----  # 헤더
    MIIDXTCCAkWgAwIBAgIJAKlqKBRWTGvhMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
    BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
    aWRnaXRzIFB0eSBMdGQwHhcNMjMwMTAxMDAwMDAwWhcNMjQwMTAxMDAwMDAwWjBF
    ....(Base64 데이터)....
    -----END CERTIFICATE-----  # 푸터

    정리하면 PEM을 아래와 같은 요소로 구성된다.

    • ASN.1: 인증서 데이터를 표현하는 규격 (이른, 만료일, 공개키 등)
    • DER: ASN.1을 바이너리로 직렬화한 것
    • Base64: 바이너리를 텍스트(A-Z, a-z, 0-9, +,/)로 변환
    • PEM: Base64에 헤더/푸터를 붙인 최종 파일

    실제 데이터 구조는 DER이고, PEM은 그것을 텍스트로 표현한 포장지이다.

    형식 정의

    PEM 데이터로 만들어진 파일은 다음과 같은 확장자로 저장한다.

    • 일반: .pem
    • 인증서: .cer 또는 .crt
    • 공개 키, 개인 키: .key

    일반적인 .pem 형식 파일이라면 데이터 유형을 정확하게 표현하기 위해 헤더를 사용한다. 헤더의 종류에는 다음과 같은 종류가 있다.

    -----BEGIN CERTIFICATE-----           # 인증서 (서버/CA 인증서)
    -----BEGIN CERTIFICATE REQUEST-----   # CSR (인증서 서명 요청)
    -----BEGIN PRIVATE KEY-----           # 개인키 (PKCS#8 포맷)
    -----BEGIN RSA PRIVATE KEY-----       # RSA 개인키 (PKCS#1 포맷)
    -----BEGIN PUBLIC KEY-----            # 공개키

    TLS에서 PEM이 쓰이는 흐름

    sequenceDiagram
        participant C as 클라이언트
        participant S as 서버
        participant CA as CA (인증기관)
    
        rect rgb(240, 248, 255)
            Note over S,CA: 사전 준비 (인증서 발급)
            S->>CA: CSR 제출 (공개키 포함)
            CA-->>S: server.crt 발급 (PEM 형식)
            Note over S: server.key (PEM) 개인키 보관
        end
    
        rect rgb(245, 255, 245)
            Note over C,S: TLS Handshake
            C->>S: ① ClientHello (지원 암호화 목록)
            S-->>C: ② ServerHello + Certificate (DER 바이너리)
            Note over C: ③ 인증서 검증 (CA 공개키로 서명 확인)
            C->>S: ④ Pre-master secret (서버 공개키로 암호화)
            Note over S: ⑤ server.key로 복호화
            Note over C,S: ⑥ 세션키 생성 (양쪽 동일)
            C->>S: ⑦ Finished (세션키 암호화)
            S-->>C: ⑦ Finished (세션키 암호화)
        end
    
        rect rgb(255, 255, 240)
            Note over C,S: 암호화 통신
            C->>S: HTTP 요청 (암호화 됨)
            S-->>C: HTTP 응답 (암호화 됨)
        end