본문으로 건너뛰기
Toova
모든 도구

MD5 대 SHA-256 대 SHA-512 — 해시 함수 설명

Toova

해시 함수는 소프트웨어 개발 어디에나 있습니다: 파일 무결성 검사, 비밀번호 저장, 디지털 서명, API 인증, 캐싱 키, 중복 제거. 그러나 대부분의 개발자는 그것들을 블랙박스로 작업합니다 — 문자열을 넣으면 고정 길이의 16진수 다이제스트를 얻습니다. 어떤 해시 함수를 사용해야 하고 어떤 것을 피해야 하는지의 세부 사항은 매우 중요하다는 것이 밝혀졌습니다.

MD5는 깨졌습니다. SHA-1은 폐기되었습니다. SHA-256과 SHA-512는 현재 안전합니다. 미래 보장을 원하면 SHA-3가 있습니다. 그러나 "깨졌다"는 것이 모든 컨텍스트에서 동일한 것을 의미하지는 않습니다 — MD5는 일부 사용 사례에는 괜찮고 다른 사례에는 재앙적으로 잘못되었습니다. 이 가이드는 중요한 속성, 각 함수가 그것들에 어떻게 맞서는지 설명하고 2026년 올바른 해시를 선택하기 위한 명확한 결정 프레임워크를 제공합니다.

해시 함수가 실제로 하는 일

암호학적 해시 함수는 임의 길이의 입력을 고정 길이 출력(다이제스트 또는 해시)에 매핑합니다. 암호학적으로 안전한 해시 함수를 정의하는 세 가지 속성:

  • 사전 이미지 저항 — 해시 h가 주어지면 hash(m) = h가 되는 어떤 입력 m도 찾는 것이 계산적으로 실행 불가능해야 합니다. 이것이 "단방향" 속성입니다.
  • 두 번째 사전 이미지 저항 — 입력 m1이 주어지면 hash(m1) = hash(m2)가 되는 다른 입력 m2를 찾는 것이 실행 불가능해야 합니다.
  • 충돌 저항hash(m1) = hash(m2)가 되는 어떤 두 개의 다른 입력 m1m2도 찾는 것이 실행 불가능해야 합니다.

이러한 속성 중 어느 것도 실패하는 함수는 암호학적 사용에 깨진 것으로 간주됩니다. "실행 불가능"은 여기서 특정한 의미가 있습니다: 수학적으로 불가능하다는 것이 아니라 현재 또는 예측 가능한 하드웨어로 실용적으로 필요한 것보다 더 많은 계산을 요구한다는 것을 의미합니다.

또한 암호학적 해시 함수는 눈사태 효과를 나타냅니다: 입력에서 단일 비트를 변경하면 비트의 약 절반에서 다른 출력이 생성됩니다. 이는 유사한 입력이 완전히 다른 다이제스트를 생성하도록 보장합니다.

입력:  "hello"
MD5:    5d41402abc4b2a76b9719d911017c592  (128비트 / 32 16진수 문자)

입력:  "Hello"
MD5:    8b1a9953c4611296a827abf8c47804d7  (한 문자 변경 = 완전히 다른 출력)

MD5 — 빠르고, 보편적이며, 깨짐

역사와 설계

MD5(Message Digest 5)는 Ron Rivest가 1991년에 설계했으며 128비트(16바이트) 다이제스트를 생성합니다. 1990년대 대부분 동안 파일 무결성 검증, 인증서 서명 및 비밀번호 해싱을 위한 표준 선택이었습니다. 매우 빠릅니다 — 현대 CPU는 초당 수천만 개의 MD5 해시를 계산할 수 있고 GPU는 수십억 개를 계산할 수 있습니다.

MD5가 깨진 이유

2004년 Xiaoyun Wang과 동료들은 MD5에 대한 실용적인 충돌 공격을 시연했습니다 — 동일한 MD5 해시를 생성하는 두 개의 다른 파일. 공격은 소비자 하드웨어에서 몇 분 만에 실행됩니다. 2008년에 연구자들은 MD5 충돌을 사용하여 악성 CA 인증서를 만들어 실제 PKI 인프라가 취약하다는 것을 시연했습니다. 2012년까지 Flame 악성 코드는 MD5 충돌을 사용하여 Microsoft 코드 서명 인증서를 위조했습니다.

NIST는 대부분의 암호학적 사용에 대해 MD5를 공식적으로 폐기했습니다. 인증 기관은 2009년까지 MD5 서명 인증서 발급을 중단했습니다. 브라우저 공급업체는 2011년경에 MD5 인증서 서명에 대한 지원을 제거했습니다.

MD5가 여전히 허용되는 때

MD5는 보편적으로 쓸모없지 않습니다. 비보안 체크섬의 경우 — 파일 전송에서 우발적인 데이터 손상 감지, 공격자가 입력에 영향을 줄 수 없는 캐싱 시스템의 콘텐츠 기반 주소 지정 또는 폐쇄된 내부 시스템에서 고유 식별자 생성 — MD5는 여전히 적절합니다. 핵심 테스트: 공격자가 충돌을 만들어 이익을 얻을 수 있다면 MD5를 사용하지 마세요. 우발적인 손상만 중요하다면 MD5는 괜찮습니다.

  • 안전함: 내부 중복 제거, 캐시 키, 비보안 파일 변경 감지
  • 안전하지 않음: 인증서, 디지털 서명, 비밀번호 해싱, 파일 진위성 검증, 보안 토큰

SHA-1 — 폐기됨, 아직 죽지는 않음

SHA-1은 160비트 다이제스트를 생성하며 MD5의 후속자였습니다. 2000년대 대부분 동안 인증서 서명과 코드 서명을 위한 표준으로 남아 있었습니다. 2017년 SHAttered 공격은 약 110 GPU년의 계산을 사용하여 동일한 SHA-1 해시를 가진 두 개의 다른 PDF 파일을 생성하여 첫 번째 실용적인 SHA-1 충돌을 시연했습니다 — 비싸지만 국가 차원의 예산 내에 있으며 점점 더 접근 가능합니다.

SHA-1은 NIST와 모든 주요 인증 기관에 의해 폐기되었습니다. 인증서, 코드 서명 또는 보안에 민감한 새 애플리케이션에 사용해서는 안 됩니다. 일부 레거시 시스템은 여전히 SHA-1을 내부적으로 사용하지만 SHA-256으로의 마이그레이션이 강력히 권장됩니다. Git은 여전히 객체 주소 지정에 SHA-1을 사용하지만(SHA-256 전환이 진행 중이긴 함) 이것은 단계적으로 폐지되고 있습니다.

SHA-256 — 현재 표준

SHA-256은 SHA-2 패밀리의 일부이며 NSA에 의해 설계되고 NIST에 의해 FIPS 180-4로 표준화되었습니다. 256비트(32바이트) 다이제스트를 생성합니다. SHA-256은 2001년 출판 이후 집중적으로 분석되었으며 실용적인 공격이 발견되지 않았습니다. 다음을 위한 사실상의 표준입니다:

  • TLS 인증서(오늘날 발급된 사실상 모든 인증서가 SHA-256 사용)
  • 코드 서명(Windows Authenticode, Apple 공증, JAR)
  • API 인증을 위한 HMAC-SHA256(AWS Signature v4, GitHub 웹훅 검증)
  • JWT 토큰 서명(HS256 및 RS256 모두 내부적으로 SHA-256 사용)
  • 블록체인 트랜잭션 ID(Bitcoin은 double-SHA256 사용)
  • 패키지 관리자의 파일 무결성 검증(npm, pip, apt)
입력:  "hello"
SHA-256: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
         (256비트 / 64 16진수 문자)

SHA-512: 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d
         99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
         (512비트 / 128 16진수 문자)

SHA-256의 성능

SHA-256은 내부적으로 32비트 워드 연산을 사용합니다. 32비트 하드웨어나 하드웨어 가속이 없는 오래된 CPU에서는 MD5보다 눈에 띄게 느립니다. SHA 확장이 있는 현대 64비트 CPU(Intel Goldmont+, AMD Zen+, Apple Silicon, ARM Cortex-A57+)에서는 SHA-256이 하드웨어 가속되며 매우 빠릅니다 — 종종 MD5 속도에 접근합니다. 대부분의 서버 환경에는 하드웨어 가속이 있으므로 실제로 SHA-256은 사실상 모든 애플리케이션에 충분히 빠릅니다.

SHA-512 — 더 넓고, 때로는 더 빠름

SHA-512는 내부적으로 64비트 워드 연산을 사용하여 512비트(64바이트) 다이제스트를 생성합니다. SHA 확장이 없는 64비트 하드웨어에서는 64비트 연산이 현대 레지스터 너비를 더 잘 활용하기 때문에 SHA-512가 실제로 SHA-256보다 빠를 수 있습니다. SHA 확장이 있는 하드웨어에서는 확장이 SHA-256에 특별히 최적화되어 있기 때문에 SHA-256이 일반적으로 더 빠릅니다.

SHA-512는 더 큰 보안 여유를 제공합니다 — SHA-256의 128비트와 비교하여 256비트 충돌 저항. 대부분의 현재 위협 모델의 경우 SHA-256의 128비트 충돌 저항은 충분합니다(이를 깨는 데 약 2^128 연산이 필요할 것입니다). SHA-512는 다음과 같은 경우에 적절합니다:

  • 64비트 서버를 대상으로 하고 하드웨어 확장 없이 최대 처리량을 원할 때
  • 다른 암호학적 연산을 위한 키 자료로 더 긴 다이제스트가 필요할 때
  • 수십 년에 걸쳐 보호되어야 하는 데이터에 추가 보안 여유를 원할 때
  • SHA-512를 특별히 요구하는 프로토콜을 구현할 때(예: 일부 TLS 암호화 슈트)

SHA-384와 SHA-512/256

SHA-384는 384비트를 생성하는 SHA-512의 절단 버전입니다 — SHA-512의 64비트 내부 연산을 원하지만 더 짧은 출력이 필요할 때 유용합니다. SHA-512/256은 SHA-512의 내부 계산을 사용하여 256비트 출력을 생성하는 또 다른 절단 변형입니다. SHA-512/256은 SHA-256에 영향을 미치는 길이 확장 공격에 저항력이 있어 길이 확장이 우려되는 컨텍스트에서 유용합니다(HMAC는 이미 대부분의 실제 시나리오에서 이를 완화합니다).

SHA-3 — 다른 아키텍처, 미래 보장

SHA-3(NIST FIPS 202, 2015에서 표준화됨)은 Keccak 스폰지 구조를 사용합니다 — SHA-2의 Merkle-Damgard 구조와 근본적으로 다른 설계. 이는 Merkle-Damgard 설계에서 발견된 미래의 약점이 MD5, SHA-1 및 SHA-2에 동시에 영향을 미칠 반면 SHA-3은 영향을 받지 않기 때문에 중요합니다.

SHA-3는 현재 안전하며 장기 보장이 필요하거나 미래 SHA-2 약점을 헤지하려는 새 시스템에 올바른 선택입니다. 순수 소프트웨어 구현에서 SHA-256보다 느립니다. SHA-3가 빛나는 곳은 하드웨어 구현입니다 — 설계가 실리콘에서 매우 효율적입니다. SHA-3-256과 SHA-3-512는 SHA-2 대응품과 동일한 다이제스트 크기를 생성합니다.

비교 표

알고리즘 출력 충돌 저항 상태 속도 (SW) 비밀번호용?
MD5 128비트 깨짐 폐기됨 매우 빠름 절대 안 됨
SHA-1 160비트 깨짐 폐기됨 빠름 절대 안 됨
SHA-256 256비트 128비트 현재 표준 빠름 (HW 가속) 절대 안 됨 (너무 빠름)
SHA-512 512비트 256비트 안전 64비트에서 빠름 절대 안 됨 (너무 빠름)
SHA-3-256 256비트 128비트 미래 보장 중간 (SW) 절대 안 됨 (너무 빠름)
bcrypt 60자 문자열 N/A 비밀번호 전용 의도적으로 느림

비밀번호 해싱: 완전히 다른 문제

이것은 개발자가 가장 흔하게 하는 실수 중 하나이기 때문에 자체 섹션이 필요합니다. SHA-256은 파일 무결성 검사, API 서명 및 인증서 검증을 위한 올바른 도구입니다. 비밀번호 해싱을 위한 잘못된 도구이며, 그 목적으로 사용하면 실제 보안 사고가 발생합니다.

문제는 속도입니다. SHA-256은 빠르도록 설계되었습니다 — 현대 GPU는 초당 수십억 개의 SHA-256 해시를 계산할 수 있습니다. 해시된 비밀번호 데이터베이스를 얻은 공격자는 초당 수십억 개의 비밀번호 추측을 시도할 수 있습니다. 해시가 빠르면 길고 무작위인 비밀번호도 빠르게 크래킹할 수 있습니다.

// 비밀번호에 절대 이렇게 하지 마세요
const hash = crypto.createHash('sha256').update(password).digest('hex');
// 비밀번호에 bcrypt, scrypt 또는 Argon2 사용
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);  // 비용 계수 12

Bcrypt Test 도구를 사용하면 브라우저에서 bcrypt 비밀번호를 해시하고 검증할 수 있습니다. bcrypt 비용 계수와 그 계산 시간을 이해하는 데 애플리케이션의 작업 계수를 설정할 때 유용한 참조입니다.

HMAC: 해시에 인증 추가

평이한 해시는 누가 계산했는지에 대해 아무것도 증명하지 않습니다 — 데이터를 가진 누구든 동일한 SHA-256 해시를 계산할 수 있습니다. HMAC(Hash-based Message Authentication Code)은 계산에 비밀 키를 추가하여 키를 아는 사람만이 재현할 수 있는 태그를 생성합니다. HMAC-SHA256은 다음을 위한 표준입니다:

  • 웹훅 서명 검증(GitHub, Stripe, Shopify 모두 HMAC-SHA256 사용)
  • AWS Signature Version 4(요청 서명)
  • JWT HS256 토큰(헤더 + 페이로드의 HMAC-SHA256)
  • 쿠키 무결성(변조 방지를 위해 세션 쿠키 서명)
const crypto = require('crypto');

// HMAC-SHA256으로 메시지 서명
const mac = crypto
  .createHmac('sha256', secretKey)
  .update(message)
  .digest('hex');

// 검증: 상수 시간으로 비교(타이밍 공격 방지)
const isValid = crypto.timingSafeEqual(
  Buffer.from(mac, 'hex'),
  Buffer.from(received, 'hex')
);

비교를 위한 timingSafeEqual 사용에 주목하세요. 일반 문자열 동등성 검사로 MAC 값을 비교하면 타이밍 공격에서 악용될 수 있는 타이밍 정보가 누출됩니다. MAC를 검증할 때 항상 상수 시간 비교 함수를 사용하세요. 코드를 작성하지 않고 테스트와 디버깅을 위해 HMAC-SHA256 값을 계산하려면 HMAC Generator를 사용하세요.

실제 권장 사항

일반 파일 무결성(체크섬)

SHA-256을 사용하세요. 패키지 검증을 위한 표준입니다(npm 잠금 파일, pip 요구 사항 해시, Docker 이미지 레이어). SHA-256 Hash 도구는 텍스트 입력이나 문자열 값에 대해 브라우저에서 SHA-256 다이제스트를 계산합니다. 속도가 중요하고 소스를 신뢰하는 빠른 비보안 체크섬의 경우 MD5는 여전히 허용되지만 공유 또는 자동화된 컨텍스트에서는 SHA-256이 더 좋습니다.

TLS 인증서와 코드 서명

SHA-256이 필수 표준입니다. 모든 인증 기관이 SHA-256 인증서를 발급합니다. 새 인증서에 MD5나 SHA-1을 절대 사용하지 마세요 — 현대 브라우저와 운영 체제에서 거부됩니다.

API 인증

HMAC-SHA256을 사용하세요. 확립된 표준이며 모든 언어에서 잘 지원되고 대부분의 API 보안 문서에서 기대하는 알고리즘입니다. 빠른 비교를 위해 MD5 Hash 도구 또는 SHA-256 Hash 도구로 다이제스트를 계산하고 HMAC Generator로 HMAC 서명을 생성하세요.

비밀번호 해싱

bcrypt(비용 계수 12+), scrypt 또는 Argon2id를 사용하세요. 솔트가 있더라도 비밀번호에 MD5, SHA-1, SHA-256 또는 SHA-512를 직접 사용하지 마세요. Bcrypt Test 도구는 개발 중 bcrypt 해시를 검증하는 데 도움이 될 수 있습니다.

수십 년의 보안이 필요한 장기 데이터

SHA-512 또는 SHA-3-256을 선호하세요. 더 큰 다이제스트 크기는 암호 분석의 발전에 대한 추가 여유를 제공합니다. NIST는 장기 보안이 필요한 애플리케이션에 SHA-512와 SHA-3를 권장합니다. SHA-2 알고리즘의 권위 있는 명세는 NIST FIPS 180-4의 공식 지침을 참조하세요.

레거시 제약이 없는 새 시스템

일반 사용에는 SHA-256. 비밀번호에는 Argon2id. 인증 코드에는 HMAC-SHA256. 미래 보장을 원하고 약간 낮은 성능을 수용할 수 있다면 SHA-3-256이 범용 해싱을 위한 SHA-256의 견고한 대안입니다.