사전 전자 서명
개념

전자 서명

gabury1고친 사람 github-actions[bot]

전자 서명은 받은 내용을 그대로 믿어도 되는지 받는 쪽이 혼자 따져 보게 해 주는 장치입니다. 누가 보냈는지와 그 뒤로 바뀌지 않았는지를 한꺼번에 봅니다. 서류에 이름을 적어 넣는 일도 같은 이름으로 부릅니다. 이 글이 다루는 것은 키 한 쌍으로 만들고 확인하는 쪽입니다.

쉽고 빠른 이해

전자 서명은 「이 내용은 내가 보낸 것이고 그 뒤로 손대지 않았다」를 받는 쪽이 혼자 확인할 수 있게 만든 값입니다. 내려받은 설치 파일에 만든 회사의 서명이 붙어 있는 것이 그 꼴입니다.

서명이 없으면 받는 쪽은 보낸 사람이 정말 그 사람인지 물어볼 데가 없습니다. 오가는 길목에서 누군가 내용을 바꿔치기해도 받는 쪽은 알아채지 못합니다.

  1. 보내는 쪽이 자기만 가진 키로 내용에 맞는 값을 만들어 붙입니다
  2. 받는 쪽이 공개된 짝 키로 그 값이 그 내용에 맞는지 따집니다
  3. 맞으면 받아들이고 아니면 버립니다

대가가 있습니다. 공개된 키가 정말 그 사람의 것인지는 서명이 알려 주지 않습니다. 그리고 자기만 가진 키가 새어 나가면 누구든 그 사람인 척 서명할 수 있습니다.

상세

친구가 보낸 음성 메시지를 떠올려 봅니다. 듣는 쪽은 무슨 말인지와 누구 목소리인지를 한 번에 알아봅니다. 한 낱말이라도 바꾸려면 친구가 그 목소리로 다시 말하는 수밖에 없습니다.

전자 서명은 같은 일을 계산으로 합니다. 그 목소리를 낼 수 있게 하는 것이 개인 키입니다. 그 목소리를 알아보게 하는 것이 공개 키입니다. 둘은 한 번에 함께 만들어지는 짝입니다. 그 짝을 키 쌍이라 부릅니다.

개인 키는 주인 말고는 아무도 몰라야 하는 값입니다. 공개 키는 반대로 아무나 가져가도 되는 값입니다. 누구나 받아 갈 수 있는 곳에 올려 둡니다. 이름이 그 쓰임을 그대로 말해 줍니다.

두 값은 한쪽으로 만든 것을 다른 쪽으로 확인할 수 있게 맞물려 있습니다. 공개 키를 아무리 들여다봐도 짝이 되는 개인 키를 되짚어 낼 수는 없습니다. 이 성질에 기대는 암호 방식을 통틀어 공개 키 암호라고 부릅니다.

한 짝이 어떻게 갈려 나가고 어느 쪽으로 되짚기가 막히는지를 아래 그림이 보입니다.

flowchart TD
    K["키 쌍"] --> P["개인 키 · 주인만 가진다"]
    K --> U["공개 키 · 누구나 가져간다"]
    U -.->|되짚을 수 없다| P

서명이 붙지 않은 메시지에는 내용만 있고 출처가 없습니다. 받는 쪽은 그 내용을 누가 보냈는지도, 오는 길에 누가 고쳤는지도 물어볼 데가 없습니다. 전자 서명은 그 두 물음에 메시지 자신이 답하게 만드는 장치입니다.

전자 서명은 서명할 내용에 맞는 값을 개인 키로 계산해 낸 값입니다. 내용이 달라지면 값이 달라집니다. 개인 키가 달라져도 값이 달라집니다. 그래서 이 값 하나가 「누가」와 「무엇을」을 같이 묶습니다.

서명과 확인이 도는 순서

만드는 쪽과 확인하는 쪽이 하는 계산은 서로 다릅니다. 양쪽 모두 메시지를 해시 함수에 한 번 넣습니다. 그 함수가 내놓는 짧은 값이 요약값입니다.

그 요약값을 개인 키로 계산한 값이 서명값입니다. 메시지에 붙어 함께 가는 것이 이 값입니다. 메시지 한 통이 오갈 때 양쪽에서 무엇을 계산하고 무엇을 주고받는지를 아래 그림이 보입니다.

sequenceDiagram
    participant S as 보내는 쪽
    participant R as 받는 쪽
    Note over S: 메시지를 해시 함수에 넣어 요약값을 낸다
    Note over S: 요약값을 개인 키로 계산해 서명값을 만든다
    S->>R: 메시지와 서명값을 함께 보낸다
    Note over R: 받은 메시지로 요약값을 다시 낸다
    Note over R: 공개 키로 서명값이 그 요약값에 맞는지 본다
    Note over R: 맞으면 받아들이고 아니면 버린다

보내는 쪽은 메시지 전체를 곧장 서명하지 않습니다. 서명 계산에 들어가는 것은 메시지가 아니라 요약값입니다.

해시 함수는 아무리 긴 입력을 넣어도 정해진 길이의 값을 내놓습니다. 입력이 한 글자만 달라져도 요약값은 전혀 다른 값이 됩니다. 그래서 요약값은 그 내용의 지문 노릇을 합니다.

요약값을 대신 서명하는 까닭은 둘입니다. 하나는 서명 계산이 정해진 크기의 값을 다룬다는 것입니다. 다른 하나는 메시지가 아무리 길어져도 붙는 서명값의 크기가 그대로 남는다는 것입니다.

입력 길이가 아무리 벌어져도 뒤의 두 값만 크기가 고정됩니다.

flowchart TD
    A["한 줄짜리 메시지"] --> A2["요약값 · 정해진 길이"]
    B["몇 기가바이트짜리 파일"] --> B2["요약값 · 같은 길이"]
    A2 --> S["서명값 · 같은 길이"]
    B2 --> S

받는 쪽은 받은 메시지를 같은 해시 함수에 넣어 요약값을 다시 뽑습니다. 그러고 나서 서명값을 공개 키로 따져 그 요약값에 맞는지 봅니다. 맞으면 그 서명은 이 메시지에 대해 짝이 되는 개인 키로 만들어진 것입니다.

맞지 않는 경우는 둘 중 하나입니다. 메시지가 도중에 바뀌었거나, 서명이 그 공개 키의 짝이 아닌 다른 키로 만들어진 것입니다. 받는 쪽은 어느 쪽인지 가릴 수 없습니다. 어느 쪽이든 버립니다.

서명 하나가 알려 주는 세 가지

서명이 확인을 통과하면 받는 쪽은 세 가지를 한꺼번에 얻습니다. 무엇을 얻는지 먼저 늘어놓고 아래에서 하나씩 풉니다.

얻는 것 무엇을 알려 주나
인증 이 내용을 그 개인 키의 주인이 만들었다
무결성 서명이 붙은 뒤로 내용이 바뀌지 않았다
부인 방지 주인이 나중에 「나는 안 했다」고 뒤집기 어렵다

인증은 보낸 사람이 누구인지를 가리는 일입니다. 서명은 그 사람 이름을 알려 주는 것이 아니라, 그 개인 키를 가진 쪽이 만들었다는 것까지를 알려 줍니다.

무결성은 내용이 온전한지를 가리는 일입니다. 요약값이 내용의 지문이므로, 내용이 바뀌면 서명은 그 내용에 더 이상 맞지 않습니다.

부인 방지는 앞의 둘과 성격이 다릅니다. 개인 키를 가진 사람이 주인 하나뿐이라는 전제 위에서만 섭니다. 키가 새어 나갔다면 이 성질도 같이 무너집니다.

메시지 인증 코드와 갈리는 대목

내용이 바뀌지 않았음을 보이는 수단이 전자 서명뿐인 것은 아닙니다. 메시지 인증 코드는 같은 일을 대칭 키 하나로 합니다. 양쪽이 같은 비밀 키를 미리 나눠 가집니다. 그 키로 계산한 값을 메시지에 붙입니다.

확인하는 쪽도 같은 키를 쓰므로 계산이 단순합니다. 대신 확인하는 쪽이 같은 값을 자기 손으로 만들어 낼 수도 있습니다. 그래서 제삼자 앞에서 「이건 저 사람이 만든 것」이라고 가릴 수 없습니다.

키를 어떻게 쓰고 무엇을 얻는지를 넷으로 견줍니다.

가르는 대목 전자 서명 메시지 인증 코드
만들 때 쓰는 키 개인 키 양쪽이 나눠 가진 같은 키
확인할 때 쓰는 키 공개 키 같은 키
확인할 수 있는 사람 공개 키를 가진 누구나 그 키를 가진 쪽만
부인 방지 ✓ ✗

부인 방지 칸에 ✗ 가 붙는 까닭은 만들 수 있는 쪽이 둘이기 때문입니다.

flowchart TD
    K["양쪽이 나눠 가진 같은 키"] --> A["보내는 쪽도 만든다"]
    K --> B["받는 쪽도 만든다"]
    A --> C["제삼자는 누가 만들었는지 못 가린다"]
    B --> C

가르는 기준은 확인하는 쪽을 어디까지 믿느냐입니다. 주고받는 둘만 내용을 따지면 되는 경우에는 메시지 인증 코드로 충분합니다. 제삼자에게 보여야 하는 경우에는 전자 서명이 필요합니다.

암호화와 갈리는 대목

전자 서명과 암호화는 둘 다 키 쌍을 씁니다. 암호화는 받는 쪽의 공개 키로 잠그고 받는 쪽의 개인 키로 엽니다. 서명은 보내는 쪽의 개인 키로 만들고 보내는 쪽의 공개 키로 확인합니다.

키 쌍의 주인이 누구이고 어느 쪽 키가 먼저 나서는지를 아래 그림이 보입니다.

flowchart TD
    subgraph ENC["암호화"]
        A["받는 쪽 공개 키"] -->|잠근다| B["암호문"]
        B -->|연다| C["받는 쪽 개인 키"]
    end
    subgraph SIG["서명"]
        D["보내는 쪽 개인 키"] -->|만든다| E["서명값"]
        E -->|확인한다| F["보내는 쪽 공개 키"]
    end

키 쌍의 주인도 다르고 공개 키와 개인 키가 나서는 차례도 반대입니다. 그래서 서명은 내용을 숨기지 않습니다. 서명이 붙은 메시지도 오가는 길에서 누구나 읽을 수 있습니다. 숨기는 일까지 필요하면 암호화를 따로 겁니다.

서명이 알려 주지 않는 것

확인을 통과한 서명이 말해 주는 것은 「이 공개 키의 짝이 만들었다」까지입니다. 그 공개 키가 정말 그 사람의 것인지는 서명 밖의 문제입니다. 가짜 키 쌍을 만들어 남의 이름을 붙여 뿌리는 일을 서명 자신은 막지 못합니다.

이 문제를 인증서가 받습니다. 인증서는 주인의 이름과 공개 키를 한 묶음으로 적은 것입니다. 양쪽이 모두 믿기로 한 인증 기관이 그 묶음에 다시 서명을 붙입니다. 인증서의 서명을 확인하려면 또 다른 공개 키가 필요합니다. 그래서 확인은 사슬이 됩니다.

flowchart TD
    A["미리 믿기로 한 키"] -->|확인해 준다| B["인증 기관의 인증서"]
    B -->|확인해 준다| C["주인의 인증서"]
    C -->|확인해 준다| D["메시지에 붙은 서명"]

사슬은 미리 믿기로 한 키에서 끝납니다. 그 키는 서명으로 확인하는 것이 아니라 기기나 프로그램에 심어 두고 믿기로 정한 것입니다. 서명이 세우는 신뢰는 이 출발점 위에 얹힙니다.

서명은 시점도 알려 주지 않습니다. 언제 서명했는지를 남기려면 시각을 내용에 넣어 함께 서명하거나 따로 타임스탬프(제삼자가 그 시각에 그 내용을 봤다고 서명해 주는 것)를 받습니다.

개인 키가 새어 나가면 서명이 주던 세 가지가 한꺼번에 무너집니다. 훔친 쪽이 주인과 구별되지 않는 서명을 만들 수 있기 때문입니다. 그래서 손이 많이 가는 곳은 서명을 만드는 계산이 아니라 키를 어디에 두고 어떻게 지키느냐입니다.

관련 항목

전자 서명을 이루는 구성 요소

개인 키 · 공개 키 · 키 쌍 · 해시 함수 · 서명값 · 요약값 · 검증

전자 서명이 지키는 성질

무결성 · 부인 방지 · 인증 · 진본성 · 충돌 저항성

전자 서명을 만드는 알고리즘

RSA · DSA · ECDSA · EdDSA · 타원 곡선 암호 · SHA-256 · 패딩

전자 서명이 기대는 신뢰 구조

인증서 · 인증 기관 · 공개 키 기반 구조 · 신뢰 사슬 · 루트 인증서 · 키 지문 · 인증서 폐기

전자 서명을 실제로 쓰는 프로토콜과 형식

TLS · JWT · SAML · OpenID Connect · 코드 서명 · 패키지 서명 · 블록체인

전자 서명을 대신할 수 있는 다른 수단

메시지 인증 코드 · HMAC · 대칭 키 · 체크섬 · 해시

전자 서명을 노리는 공격과 그 한계

개인 키 유출 · 중간자 공격 · 생일 공격 · 재전송 공격 · SHA-1

전자 서명과 함께 쓰는 암호 수단

암호화 · 공개 키 암호 · 키 교환 · 난수 · 타임스탬프

다른 이름: 디지털 서명 · digital signature