해시·HMAC·전자서명 비교: 무결성과 발신자 검증의 차이

1장 개념과 보호 목표#

해시는 임의 길이 입력을 일정한 형태의 요약값으로 변환합니다. HMAC은 비밀키를 공유하는 당사자 사이에서 메시지 인증을 제공하고, 전자서명은 개인키로 생성한 값을 공개키로 검증합니다. 공격자가 무엇을 바꿀 수 있는지에 따라 적절한 수단이 달라집니다.


2장 원리와 구분#

역상 저항성은 해시값에서 입력을 찾기 어렵다는 성질, 제2역상 저항성은 주어진 입력과 같은 해시의 다른 입력을 찾기 어렵다는 성질, 충돌 저항성은 같은 해시의 두 입력을 찾기 어렵다는 성질입니다. MD5와 SHA-1은 충돌 저항성이 필요한 새 설계에 적합하지 않습니다. 단순 SHA-256은 빠르기 때문에 비밀번호 저장용 KDF를 대체하지 못합니다.


3장 비교와 판단 기준#

수단 키 검증·신뢰의 범위
SHA-2·SHA-3 비밀키 없음 요약값, 기준값 신뢰 필요
HMAC 공유 비밀키 키 보유 당사자 간 인증
전자서명 개인키·공개키 발급·신뢰 체계와 함께 검증
비밀번호 KDF 비밀번호·Salt 저장 검증값, 대입 비용 증가

4장 파일 해시가 같다는 사실은 무엇을 말할까#

동일한 입력 바이트를 같은 해시 함수로 계산하면 동일한 출력이 나옵니다. 전송 전후의 파일 해시가 다르면 변경이나 처리 차이를 의심할 수 있습니다. 하지만 공격자가 파일과 기준 해시를 모두 바꾸면 일치 검사는 그대로 통과할 수 있습니다. 기준값을 받은 경로와 배포자의 신뢰가 필요합니다.

해시는 암호문이 아니어서 키로 복호화하는 절차가 없습니다. 그렇다고 작은 후보 집합의 입력을 숨기는 효과까지 보장되지는 않습니다. 흔한 전화번호나 상태값은 후보를 대입해 비교할 수 있으므로 해시 저장만으로 익명화라고 판단하면 안 됩니다.


5장 충돌·원상·제2원상은 다른 질문이다#

충돌은 같은 출력이 나오는 서로 다른 두 입력을 찾는 문제입니다. 원상은 주어진 출력의 입력을 찾는 문제, 제2원상은 특정 입력과 같은 출력의 다른 입력을 찾는 문제입니다. 공격자가 어떤 값을 미리 정할 수 있는지에 따라 요구 성질이 달라집니다.

성질 공격자가 찾으려는 것 구분할 질문
원상 저항성 주어진 해시의 입력 출력에서 거꾸로 찾는가?
제2원상 저항성 정해진 입력과 같은 해시의 다른 입력 원본이 미리 정해졌는가?
충돌 저항성 같은 해시의 임의의 두 입력 두 입력을 모두 고르는가?

6장 출력 길이와 생일 효과#

이상적인 n비트 해시의 출력 후보는 2^n개입니다. 아무 두 입력의 출력이 겹치는 충돌 탐색은 대략 2^(n/2) 규모의 생일 효과와 연결됩니다. 특정 출력 하나의 원상을 찾는 문제와 같은 비용으로 설명하지 않습니다. 실제 함수의 취약점은 이 이상적 관계와 별도로 조사합니다.

SHA-256이라는 이름의 256비트를 충돌 공격에 대한 256비트 강도라고 그대로 읽으면 안 됩니다. 키 강도·출력 길이·실제 공격 비용이 어떤 질문에 대한 수치인지 함께 확인합니다.


7장 HMAC는 단순한 비밀 문자열 결합과 다르다#

HMAC는 키와 해시를 정해진 구조로 결합하는 메시지 인증 코드입니다. 임의로 H(key || message)만 계산한 자체 방식과 동일하게 취급해서는 안 됩니다. 표준 HMAC 구현은 키 처리와 구조를 규정하므로 라이브러리의 해당 기능을 사용합니다.

같은 키를 가진 검증자도 올바른 인증값을 생성할 수 있습니다. 따라서 공동 비밀을 공유한 두 상대 중 누가 메시지를 만들었는지 제3자에게 독립적으로 증명하는 목적은 전자서명과 다릅니다. 키의 공유 범위를 최소화해야 사고 영향도 줄어듭니다.

flowchart LR
 M["메시지"] --> H["HMAC 계산"]
 K["공유 비밀키"] --> H
 H --> T["인증값"]
 M --> V["수신자의 HMAC 재계산"]
 K --> V
 V --> C["안전한 비교"]
 T --> C

8장 웹훅 검증에서 원본 바이트가 중요한 이유#

발신자가 요청 본문의 원본 바이트에 HMAC를 계산했는데 수신자가 JSON을 파싱하고 다시 직렬화한 값으로 계산하면 정상 요청도 실패할 수 있습니다. 숫자·공백·필드 순서·문자 인코딩의 차이가 입력 바이트를 바꾸기 때문입니다. 규약이 요구한 원본 또는 정규화 형식을 사용합니다.

인증값이 맞아도 같은 요청을 다시 실행하는 재전송이 남습니다. 서명된 타임스탬프·이벤트 ID를 검증하고 허용 시간과 중복 소비를 관리합니다. 허용 시간만으로 동시 중복 실행을 막는지, 원자적 처리도 필요한지 시험해야 합니다.

웹훅 수신
→ 요청 크기와 형식 확인
→ 정해진 원본 바이트 확보
→ HMAC 검증
→ 시간과 이벤트 중복 검사
→ 업무 권한·상태 확인
→ 한 번만 반영

9장 전자서명의 생성권과 검증권#

개인키 보유자는 서명을 생성하고 공개키를 아는 상대는 검증할 수 있습니다. 검증자에게 서명 생성 비밀을 공유하지 않아도 된다는 점이 HMAC와 큰 차이입니다. 다만 공개키가 정말 의도한 작성자의 키인지 확인하는 신뢰 경로가 필요합니다.

서명값이 맞다는 것은 정해진 키와 데이터의 관계를 검증했다는 뜻입니다. 서명자의 직책·승인 권한과 내용의 진실성은 업무 정책과 다른 증거로 판단합니다. 키가 탈취되면 공격자도 정상처럼 보이는 서명을 만들 수 있습니다.

flowchart TB
 D["배포 파일"] --> S["작성자 개인키로 서명"]
 S --> T["서명값"]
 D --> V["공개키로 검증"]
 T --> V
 P["신뢰 경로로 확인한 공개키"] --> V
 V --> R["서명과 데이터 일치 확인"]

10장 배포 파일의 세 가지 검증 수준#

다운로드한 파일의 해시만 계산하면 기준 없이 요약값을 얻은 상태입니다. 신뢰할 배포 경로의 해시와 비교하면 전송된 내용의 일치를 확인할 수 있습니다. 신뢰하는 키의 서명까지 검증하면 해당 키로 서명된 배포 데이터와의 연결을 확인할 수 있습니다.

서명 파일과 공개키를 같은 공격 가능한 경로에서 무검증으로 받아들이면 신뢰가 성립하지 않을 수 있습니다. 키를 처음 신뢰하는 방법, 교체와 폐지, 파일 형식과 서명 대상 범위를 설계해야 합니다.


11장 비밀번호·메시지·파일에 같은 해시 사용법을 적용하지 않는다#

비밀번호는 낮은 엔트로피의 후보를 느리게 검증하는 전용 KDF가 필요합니다. 메시지 인증은 HMAC나 서명으로 비밀 또는 공개키 신뢰를 연결합니다. 파일 변경 비교는 신뢰하는 기준 해시가 필요합니다. 모두 해시 함수가 관련될 수 있지만 사용 조건과 방어 목표는 다릅니다.

검토 문서에 SHA-256 사용이라고만 적기보다 입력·목적·키·Salt·비용·기준값·검증 시점 중 해당하는 항목을 기록합니다. 이렇게 하면 서로 다른 보안 요구를 같은 알고리즘 이름으로 덮는 실수를 줄일 수 있습니다.


12장 실패 시험으로 신뢰 경계를 확인한다#

메시지 한 바이트 변경, 다른 비밀키, 서명 대상의 변경, 잘못된 공개키, 만료·폐지 정책, 동일 이벤트의 재전송을 각각 시험합니다. 비교 실패가 업무 처리 전에 발생하는지와 실패 값을 정상 값으로 바꾸는 코드가 없는지 확인합니다.

로그에는 검증 결과와 식별자를 남기되 공유 비밀·원문 비밀번호·민감한 요청 전체를 무조건 남기지 않습니다. 진본 검증과 기록의 보호를 함께 설계해야 조사할 수 있는 안전한 운영이 됩니다.


13장 적용 사례와 운영 방법#

서버 간 요청에 HMAC을 붙일 때는 본문뿐 아니라 시간·경로·요청 ID를 포함하고 재전송을 제한합니다. 서명은 서명키 보관, 인증서 신뢰와 감사기록이 결합되어야 행위 증명에 도움이 됩니다. HMAC 키를 가진 양쪽 모두 태그를 만들 수 있으므로 제3자에 대한 부인방지 성질은 전자서명과 다릅니다.


14장 검증자가 무엇을 신뢰하는지부터 정한다#

단순 해시는 데이터에 비밀을 넣지 않고 계산합니다. 공격자가 파일과 해시를 모두 바꿀 수 있다면 두 값이 일치해도 진본이라고 판단할 수 없습니다. HMAC는 공유 비밀을 가진 상대의 메시지를 검증하는 데 사용하지만 검증자도 같은 키로 인증값을 만들 수 있습니다. 전자서명은 개인키로 만들고 공개키로 검증해 검증 권한과 생성 권한을 나눕니다.

해시 함수의 출력 길이와 충돌 저항성은 구분합니다. 이상적인 n비트 해시에서 무작위 충돌 탐색의 복잡도는 대략 2^(n/2), 특정 출력의 원상 탐색은 대략 2^n입니다. 이 관계만으로 실제 함수의 안전성을 보증하지는 않으며 깨진 함수나 부적절한 구현을 배제해야 합니다.


15장 배포 파일과 웹훅은 서로 다른 검증이 필요하다#

공개 배포 파일은 신뢰할 수 있는 경로의 해시와 비교하거나 신뢰하는 서명자의 공개키로 검증합니다. 웹훅은 공유 비밀 기반 HMAC에 타임스탬프와 이벤트 ID를 결합하고 허용 시간·중복 처리를 검사할 수 있습니다. 올바른 인증값이 있는 메시지를 다시 보내는 재전송은 HMAC 비교만으로 막히지 않습니다.

서명 검증도 인증서 체인, 서명 대상 바이트, 알고리즘 허용 정책을 포함해야 합니다. JSON을 다시 직렬화하면서 공백이나 필드 순서를 바꾸면 서명 입력이 달라질 수 있으므로 규약이 정한 원본 바이트나 정규화 형식을 사용합니다.


16장 적용 전 확인할 사항#

  • 해시값의 신뢰 경로를 확보한다
  • HMAC 입력의 정규화와 재전송 방지를 정한다
  • 서명 검증 시 메시지·알고리즘·키의 용도를 확인한다

17장 자주 묻는 질문#

SHA-3는 SHA-256의 단순한 상위 버전인가요?#

SHA-3는 SHA-2와 구조가 다른 해시 표준입니다. 용도·프로토콜 지원·성능과 요구 조건에 따라 선택하며 버전 숫자만으로 일괄 교체할 필요는 없습니다.

체크섬과 SHA-256은 같은 용도로 써도 되나요?#

체크섬은 주로 우발적 오류 검출에 쓰입니다. 공격자가 의도적으로 데이터를 바꾸는 위협에는 암호학적 해시와 신뢰할 기준값, 필요하면 HMAC·서명을 사용해야 합니다.

서명 검증 성공은 내용이 사실이라는 뜻인가요?#

서명된 데이터가 해당 키로 생성되고 변경되지 않았다는 검증입니다. 작성자의 신원 연결과 내용의 사실성은 별도로 판단해야 합니다.


함께 읽기#