MD5란 무엇인가? 해시 함수 원리·충돌 위험과 올바른 사용 상황

큰 파일을 다운로드하면 다운로드 페이지 옆에 d41d8cd98f00b204e9800998ecf8427e와 같은 이상한 문자열과 "MD5"라는 표기를 종종 봅니다. 이게 무엇이고 무엇을 의미하는 걸까요? 이 글에서는 해시 함수의 기본 개념부터 시작해 MD5의 작동 원리, 보안 현황, 그리고 상황에 맞는 해시 알고리즘 선택 방법을 완벽하게 설명합니다.

1. 해시 함수란 무엇인가?

해시 함수(Hash Function)는 임의 길이의 입력 데이터를 고정 길이의 출력값(「해시값」「다이제스트」라고 함)으로 변환하는 수학 함수입니다. 좋은 해시 함수는 다음 특성을 가집니다:

  • 결정론적: 같은 입력은 항상 같은 출력을 생성
  • 고정 길이 출력: 입력 길이와 무관하게 출력 길이가 고정됨 (MD5는 128비트 = 32자리 16진수)
  • 눈사태 효과: 입력의 1비트가 바뀌면 출력의 약 50% 비트가 변화
  • 단방향성 (역상 저항성): 해시값에서 원래 입력을 역산하는 것이 계산상 거의 불가능
  • 충돌 저항성: 같은 출력을 내는 두 다른 입력을 찾기 어려움
해시 ≠ 암호화
암호화는 가역적입니다 (올바른 키로 복호화 가능). 해시는 단방향이며 복원 불가능합니다. 둘은 근본적으로 다른 용도이며, 혼동하면 심각한 보안 문제가 발생합니다.

2. MD5의 작동 원리

MD5(Message Digest Algorithm 5)는 Ron Rivest가 1991년 MD4의 개선판으로 설계했습니다. 128비트(16바이트) 출력을 생성하며, 일반적으로 32자리 소문자 16진수로 표현합니다.

2.1 처리 흐름 개요

  1. 패딩(Padding): 입력 데이터를 512로 나누어 448비트 나머지가 되도록 채우고, 원본 길이를 64비트로 뒤에 추가
  2. 초기화: 4개의 32비트 상태값(A, B, C, D)을 고정 상수로 초기화
  3. 블록 처리: 패딩된 데이터를 512비트 블록으로 분할하고, 각 블록에 4라운드 총 64회의 비선형 연산 적용
  4. 출력: 최종 4개의 32비트값을 연결해 128비트 다이제스트 생성

2.2 예시

같은 입력은 항상 같은 MD5를 생성합니다:

MD5("") = d41d8cd98f00b204e9800998ecf8427e
MD5("hello") = 5d41402abc4b2a76b9719d911017c592
MD5("Hello") = 8b1a9953c4611296a827abf8c47804d7

"hello"와 "Hello"는 대소문자 하나만 다르지만 MD5값은 완전히 다릅니다——눈사태 효과의 발현입니다.

3. MD5의 보안 문제

3.1 충돌 공격(Collision Attack)

2004년 왕샤오윈 교수 팀이 MD5 충돌——즉 두 다른 입력이 완전히 같은 MD5값을 생성——을 성공적으로 발견했습니다. 이는 공격자가 합법적인 파일과 동일한 MD5를 가진 악의적인 파일을 만들어 무결성 검증을 우회할 수 있음을 의미합니다.

2008년에는 연구자들이 MD5 충돌을 이용해 가짜 SSL 인증서를 위조하며 현실 세계 공격의 가능성을 입증했습니다.

3.2 레인보우 테이블 공격

MD5는 계산 속도가 매우 빠릅니다——현대 GPU는 초당 수십억 개의 MD5를 계산할 수 있습니다. 공격자는 "평문→MD5값" 대조표(레인보우 테이블)를 사전에 구축해, 저장 공간과 속도를 맞바꿔 암호의 평문을 빠르게 역조회할 수 있습니다.

이것이 현대 비밀번호 저장에 MD5(또는 SHA-1, SHA-256)를 직접 사용해서는 안 되는 이유입니다——솔트를 추가해도 비밀번호 전용으로 설계된 함수만큼 안전하지 않습니다.

3.3 길이 확장 공격(Length Extension Attack)

MD5(SHA-1, SHA-256도 마찬가지)는 길이 확장 공격에 취약합니다. 공격자는 원본 데이터를 모르더라도 유효한 MAC(메시지 인증 코드)을 위조할 수 있습니다. SHA-3과 HMAC 구조는 이 공격에 영향을 받지 않습니다.

4. MD5 vs 다른 해시 알고리즘

알고리즘출력 길이보안성속도적합한 용도
MD5128 bit파손됨 (충돌 공지)매우 빠름비보안 체크섬만
SHA-1160 bit파손됨 (2017년 실제 충돌)빠름새 시스템 비권장
SHA-256256 bit안전 (알려진 충돌 없음)보통디지털 서명·인증서·일반 보안
SHA-3가변안전 (다른 설계 원리)느린 편고보안 요구사항
bcrypt고정비밀번호 전용 설계, 무차별 대입 저항느림 (의도적 설계)비밀번호 저장
Argon2가변PHC 2015 우승느림 (의도적 설계)비밀번호 저장 (권장)

5. MD5의 올바른 사용 상황

5.1 ✅ 비보안 파일 무결성 확인

다운로드나 전송 중 파일이 손상되지 않았는지 확인 (주의: 악의적 변조는 방지할 수 없음). 악의적 변조가 우려된다면 SHA-256을 사용하세요.

5.2 ✅ 중복 제거와 캐시 키

MD5를 콘텐츠의 고유 식별자로 사용해 두 데이터가 동일한지 판단하거나 캐시 시스템의 키로 사용. 보안과 무관하며 MD5의 결정론적 특성과 속도만 활용합니다.

5.3 ✅ 비비밀번호 데이터 인덱싱

대량의 텍스트에 MD5를 계산해 데이터베이스 인덱스 키로 사용. 고정 길이와 균등 분포 특성으로 검색 효율을 높입니다.

5.4 ❌ 비밀번호 저장

MD5(또는 범용 해시 함수)로 비밀번호를 저장하는 것은 절대 금지입니다. bcrypt, Argon2, scrypt 같은 비밀번호 전용 함수를 사용하세요.

5.5 ❌ 디지털 서명과 인증서

MD5의 충돌 취약점으로 X.509 인증서 서명, 코드 서명, 위조 방지가 필요한 모든 상황에는 부적합합니다. SHA-256 이상을 사용하세요.

5.6 ❌ HMAC 기반 해시

HMAC-MD5는 이론적으로 순수 MD5보다 안전하지만, 현대 시스템에서는 HMAC-SHA256으로 전환을 권장합니다.

6. MD5 계산 방법

# 명령줄 (Linux/macOS)
md5sum file.txt          # Linux
md5 file.txt             # macOS

# PHP
md5('hello')             // 5d41402abc4b2a76b9719d911017c592
md5_file('file.txt')     // 파일의 MD5 계산

# Python
import hashlib
hashlib.md5(b'hello').hexdigest()

# JavaScript (crypto-js 라이브러리 사용)
CryptoJS.MD5('hello').toString()

또는 이 사이트의 MD5 도구를 사용해 브라우저에서 바로 텍스트의 MD5값을 계산하세요——소프트웨어 설치 필요 없습니다.

7. 자주 묻는 질문

7.1 MD5와 Base64의 차이는 무엇인가요?

MD5는 해시(단방향, 복원 불가), Base64는 인코딩(양방향, 복원 가능)입니다. 성질이 근본적으로 다르며 혼용하면 보안 문제가 발생합니다.

7.2 솔트(Salt)를 추가하면 MD5로 비밀번호를 저장할 수 있나요?

솔트는 레인보우 테이블 공격을 막을 수 있지만 MD5가 너무 빠르다는 근본 문제는 해결되지 않습니다. 솔트를 추가해도 현대 GPU는 초당 수십억 번 시도할 수 있습니다. bcrypt나 Argon2를 사용하세요.

7.3 "MD5 충돌"이란 무엇이고 왜 중요한가요?

충돌이란 두 다른 입력이 같은 MD5값을 생성하는 것입니다. 현재 몇 초 만에 MD5 충돌을 생성하는 도구가 존재하며, 공격자는 합법적인 파일과 동일한 MD5를 가진 악의적 파일을 만들어 MD5 검증에 의존하는 시스템을 속일 수 있습니다.

8. 정리

MD5는 잘 설계되고 널리 배포된 해시 알고리즘이지만 암호학적 보안은 이미 깨진 상태입니다. 그 한계를 이해하는 것은 모든 개발자의 기본 지식입니다: 비보안 무결성 확인과 데이터 식별에는 여전히 유용하지만, 비밀번호 저장·디지털 서명·악의적 공격 저항이 필요한 상황에서는 사용해서는 안 됩니다. 그런 상황에서는 SHA-256(범용) 또는 Argon2(비밀번호)가 올바른 선택입니다.