해시 함수란
해시 함수는 임의 길이의 입력을 고정 길이의 출력(해시값, 다이제스트)으로 바꾸는 함수다. 입력이 1바이트든 1기가바이트든 SHA-256이라면 항상 256비트 출력이 나온다. 대칭키·비대칭키 암호화와 달리 해시에는 키가 없고, 되돌리는 연산도 정의되어 있지 않다.
시험에서 묻는 해시 함수의 핵심 성질은 세 가지다.
- 일방향성(one-way): 출력값에서 입력값을 역산할 수 없어야 한다. 이 성질 때문에 비밀번호를 원문 대신 해시값으로 저장한다.
- 충돌 회피성(collision resistance): 서로 다른 두 입력이 같은 출력을 내는 경우(충돌)를 찾기 어려워야 한다. 임의의 두 입력이 우연히 충돌할 확률이 낮아야 한다는 약한 충돌 회피성과, 주어진 입력과 충돌하는 다른 입력을 찾기 어려워야 한다는 강한 충돌 회피성으로 나뉜다.
- 눈사태 효과(avalanche effect): 입력을 한 비트만 바꿔도 출력이 완전히 달라져야 한다. 입력의 유사성을 출력에서 추측할 수 없게 만드는 성질이다.
MD5와 SHA-1은 한때 널리 쓰였지만 실제로 충돌이 발견되어 지금은 무결성 검증 용도로 권장하지 않는다. SHA-256을 포함한 SHA-2 계열, 그리고 SHA-3가 현재 표준적으로 쓰인다.
전자서명의 구조
전자서명은 “이 문서를 누가 썼고, 보낸 뒤 바뀌지 않았다”를 증명하는 수단이다. 비대칭키 암호화를 기밀성이 아니라 검증 목적으로 뒤집어 쓴다는 점이 핵심이다.
절차는 이렇다.
- 송신자가 원문을 해시 함수에 넣어 다이제스트를 만든다.
- 그 다이제스트를 송신자의 개인키로 암호화한다 — 이것이 서명값이다.
- 원문과 서명값을 함께 보낸다.
- 수신자는 같은 해시 함수로 원문의 다이제스트를 다시 계산하고, 송신자의 공개키로 서명값을 복호화해 다이제스트를 얻는다.
- 두 다이제스트가 같으면 서명이 유효하다.
기밀성을 위한 비대칭키 암호화는 “공개키로 암호화 → 개인키로 복호화” 순서지만, 전자서명은 정반대로 “개인키로 암호화(서명) → 공개키로 복호화(검증)” 순서를 쓴다. 개인키는 서명자만 갖고 있으므로, 서명이 검증되면 그 개인키를 가진 사람이 서명했다는 뜻이 된다.
원문 전체가 아니라 해시값을 서명하는 이유는 효율이다. 비대칭키 연산은 대칭키보다 훨씬 느리므로, 큰 문서 전체를 암호화하는 대신 고정 길이의 다이제스트만 암호화한다.
전자서명이 제공하는 것과 제공하지 않는 것
전자서명은 세 가지 보안 서비스를 제공한다.
- 인증(authentication): 서명이 특정 개인키 소유자에게서 나왔음을 확인한다.
- 무결성(integrity): 원문이 서명 이후 변경되지 않았음을 확인한다. 한 글자만 바뀌어도 해시값이 달라져 검증이 실패한다.
- 부인 방지(non-repudiation): 서명자가 나중에 “내가 서명한 게 아니다”라고 부인할 수 없다. 개인키는 본인만 갖고 있어야 하기 때문이다.
주의할 점은 전자서명 자체가 기밀성을 제공하지 않는다는 것이다. 원문은 평문으로 함께 전송되므로, 내용을 숨기려면 별도로 암호화해야 한다. 또한 공개키가 정말 그 사람의 것인지는 전자서명만으로는 보장되지 않아서, 공개키를 신원과 묶어 보증하는 인증기관(CA)의 공개키 인증서가 함께 쓰인다.
시험 포인트
해시 함수의 세 성질(일방향성·충돌 회피성·눈사태 효과)을 각각 구분해서 물어보는 문제가 나온다. MD5·SHA-1이 취약하다는 사실과 SHA-256이 대안이라는 점도 자주 나온다. 전자서명 문제는 “개인키로 서명, 공개키로 검증”이라는 방향을 비대칭키 암호화의 “공개키로 암호화, 개인키로 복호화”와 헷갈리게 내는 경우가 많으니 목적(기밀성 vs 인증)으로 구분해서 외우는 편이 안전하다. 전자서명이 기밀성을 제공하지 않는다는 점, 인증서와 CA의 역할도 자주 출제되는 포인트다.
이 글에 대한 의견은 아래 댓글로 남겨주세요 (GitHub 계정 필요). 로그인 없이 남기고 싶다면