광고
~ / posts / developer
smith@lab:~/posts$ cat developer/hash-md5-sha256-difference.md

MD5 SHA-1 SHA-256 차이, 해시와 암호화·체크섬 확인법 정리

다운로드 페이지 옆에 붙은 SHA256: 2cf24dba… 같은 긴 문자열, DB에 저장된 비밀번호 칸의 알 수 없는 글자, 웹훅 요청 헤더의 X-Hub-Signature-256. 전부 해시인데, 막상 "MD5랑 SHA-256은 뭐가 다르고, 해시는 암호화랑 뭐가 다르냐"고 물으면 설명이 꼬이더라고요. 결론부터 말하면 해시는 어떤 데이터든 고정 길이 지문으로 바꾸는 단방향 함수라서 원래 값으로 되돌릴 수 없고, 암호화는 키만 있으면 되돌릴 수 있는 양방향 변환이에요. 그리고 MD5와 SHA-1은 서로 다른 두 입력이 같은 지문을 갖는 "충돌"이 실제로 만들어져서 보안 용도로는 끝났고, 지금 기본값은 SHA-256입니다.

이 글에서는 해시·암호화·인코딩의 차이, MD5·SHA-1·SHA-256의 길이와 안전성 비교, 다운로드한 파일의 체크섬을 운영체제별로 확인하는 명령어, MD5와 SHA-1이 깨진 실제 사례, 비밀번호 저장에 SHA-256이 아니라 bcrypt·Argon2를 써야 하는 이유, 그리고 API 서명에 쓰는 HMAC까지 순서대로 정리할게요. 문자열을 바로 해시해 보고 싶다면 해시 생성기에서 알고리즘별 결과를 한 번에 볼 수 있어요.

광고

해시 함수란? 암호화·인코딩과의 차이

해시 함수는 길이가 제각각인 입력을 받아 항상 같은 길이의 값을 내놓는 함수예요. "hello" 다섯 글자를 넣어도, 4GB짜리 ISO 파일을 넣어도 SHA-256 결과는 똑같이 256비트(16진수 64자)예요. 실제로 계산해 보면 이렇습니다.

입력SHA-256 결과 (16진수 64자)
hello2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Hello185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969
hello.1589999b0ca6ef8814283026a9f166d51c70a910671c3d44049755f07f2eb910
(빈 문자열)e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

hello 와 Hello 는 첫 글자 대소문자 하나 차이인데, 결과 256비트 중 125비트가 달라요. 거의 절반이 뒤집힌 거죠. 이걸 눈사태 효과(avalanche effect)라고 하고, 좋은 해시의 기본 조건이에요. 결과만 보고 "입력이 비슷했겠구나"를 짐작할 수 없어야 하니까요. 빈 문자열의 해시 e3b0c442… 는 로그에서 자주 보이니 기억해 두면 좋아요.

암호용 해시 함수는 세 가지 성질을 가져야 해요.

해시 vs 암호화 vs 인코딩

세 가지가 자주 섞여 쓰이는데 목적이 완전히 달라요.

구분되돌리기키 필요목적예
인코딩누구나 가능없음형식 변환Base64, URL 인코딩
암호화키 있으면 가능있음비밀 유지AES, RSA
해시불가능없음(HMAC은 있음)무결성·식별SHA-256, MD5

"비밀번호를 MD5로 암호화했다"는 말은 엄밀히 틀린 표현이에요. 해시는 복호화가 없어요. 대신 같은 입력이면 같은 값이 나오니까, 사람들이 자주 쓰는 비밀번호를 미리 해시해 둔 표(레인보우 테이블)와 대조하면 원문이 드러나요. 되돌리는 게 아니라 맞혀 보는 거죠. Base64를 암호화로 착각하는 실수는 Base64는 암호화가 아니다 글에서 따로 다뤘어요.

같은 입력 hello를 인코딩·암호화·해시에 넣었을 때 인코딩은 누구나 되돌리고, 암호화는 키로만 되돌리고, 해시는 되돌릴 수 없는 고정 길이 지문이 되는 차이를 비교한 카드
해시는 되돌리는 게 아니라 같은 입력인지 대조하는 지문이에요

MD5 SHA-1 SHA-256 차이 한눈에 보기

세 알고리즘의 가장 큰 차이는 출력 길이와 지금도 안전한가예요. 출력이 길수록 우연히 겹칠 확률이 낮아지는데, 생일 문제 때문에 n비트 해시의 충돌은 대략 2^(n/2)번 시도하면 찾을 수 있어요. 그래서 설계상 충돌 저항 강도는 출력 길이의 절반이에요.

알고리즘발표출력16진수 길이설계상 충돌 강도현재 상태
MD51992 (RFC 1321)128비트32자2⁶⁴충돌 생성이 일반 PC로 수 초. 보안 용도 금지
SHA-11995 (FIPS 180-1)160비트40자2⁸⁰2017년 실제 충돌 공개. NIST는 2030년까지 퇴출 예정
SHA-2562001 (SHA-2)256비트64자2¹²⁸알려진 실용 공격 없음. 현재 표준
SHA-5122001 (SHA-2)512비트128자2²⁵⁶안전. 64비트 CPU에서 SHA-256보다 빠를 때도 있음
SHA3-2562015 (FIPS 202)256비트64자2¹²⁸안전. SHA-2와 내부 구조가 완전히 다름
해시 알고리즘별 출력 길이 (16진수 글자 수)
MD5MD5 · 32자32자SHA-1SHA-1 · 40자40자SHA-256SHA-256 · 64자64자SHA3-256SHA3-256 · 64자64자SHA-512SHA-512 · 128자128자

해시값 길이만 보고도 알고리즘을 짐작할 수 있어요. 32자면 MD5, 40자면 SHA-1일 가능성이 커요.

단위: 자 · 자료: 출력 비트 ÷ 4 (16진수 1자 = 4비트)로 계산
표로 보기
구분16진수 길이
MD532
SHA-140
SHA-25664
SHA3-25664
SHA-512128

길이로 알고리즘을 짐작하는 건 디버깅할 때 꽤 유용해요. 40자는 Git 커밋 해시 길이이기도 하고, SHA3-256도 64자라 길이만으로 확정할 순 없어요. 참고로 SHA-2는 SHA-224·256·384·512를 묶은 가족 이름이고 숫자는 출력 비트 수예요.

파일 체크섬 확인하는 법 (Windows·macOS·리눅스)

리눅스 ISO나 개발 도구를 받을 때 배포 페이지에 함께 적힌 SHA-256 값을 체크섬이라고 해요. 내가 받은 파일을 직접 해시해서 그 값과 똑같으면, 다운로드 도중 깨지지 않았고 중간에 바뀌지 않았다는 뜻이에요.

# Windows (명령 프롬프트)
certutil -hashfile ubuntu.iso SHA256

# Windows (PowerShell) — 기본 알고리즘이 SHA256
Get-FileHash .\ubuntu.iso

# macOS
shasum -a 256 ubuntu.iso

# 리눅스
sha256sum ubuntu.iso

# 배포처가 준 SHA256SUMS 파일로 한 번에 대조 (리눅스)
sha256sum -c SHA256SUMS --ignore-missing

확인할 때 몇 가지를 조심하세요.

  1. 알고리즘을 맞추세요. 배포처가 SHA-256을 줬는데 MD5로 계산하면 당연히 달라요. 길이부터 비교해 보면 바로 알 수 있어요.
  2. 대소문자는 상관없어요. certutil 은 소문자, Get-FileHash 는 대문자로 출력하지만 같은 값이에요.
  3. 눈으로 앞 몇 자만 보지 마세요. 비교는 전체 64자를 해야 해요. PowerShell에서는 (Get-FileHash .\파일).Hash -eq "배포처값" 처럼 비교식을 쓰면 True/False로 바로 나와요.
  4. 같은 서버의 체크섬은 한계가 있어요. 서버가 해킹당해 파일과 체크섬을 함께 바꿔 놓으면 체크섬은 일치해요. 그래서 우분투 같은 배포처는 SHA256SUMS 파일에 GPG 서명(SHA256SUMS.gpg)을 따로 붙여요. 체크섬은 "전송 중 손상"을, 서명은 "배포자가 맞는지"를 확인하는 거예요.
배포처가 공개한 SHA-256 값과 내가 받은 파일을 직접 해시한 값을 비교해 일치하면 정상, 다르면 다시 받거나 출처를 의심하는 체크섬 검증 순서도
체크섬은 손상을, GPG 서명은 배포자를 확인해요

왜 MD5와 SHA-1은 깨졌다고 할까

"깨졌다"는 말은 해시값에서 원래 비밀번호를 복원할 수 있게 됐다는 뜻이 아니에요. 같은 해시값을 갖는 서로 다른 두 파일을 일부러 만들 수 있게 됐다는 뜻이에요. 그게 왜 문제냐면, 전자 서명과 인증서는 문서 전체가 아니라 문서의 해시에 서명하거든요. 해시가 같은 두 문서를 만들 수 있으면, 무해한 문서에 받은 서명을 악성 문서에 그대로 옮겨 붙일 수 있어요.

MD5: 2004년 충돌, 2008년 가짜 인증서

SHA-1: 2017년 SHAttered

2017년 2월 구글과 네덜란드 CWI 연구소가 SHAttered 공격을 발표했어요. 내용은 다르지만 SHA-1 해시가 완전히 같은 PDF 파일 두 개를 실제로 만들어 공개한 거예요. 계산량은 SHA-1 연산 약 9.2×10¹⁸번(약 2⁶³)으로, 연구팀 설명으로는 CPU 6,500년치와 GPU 110년치에 해당했어요. 설계상 2⁸⁰번이 필요하다던 것보다 10만 배 이상 적은 양이었죠.

2020년에는 "SHA-1 is a Shambles" 연구가 선택 접두 충돌로 PGP 키 위조까지 시연했어요. 브라우저들은 2017년 무렵 SHA-1 인증서 신뢰를 끊었고, NIST는 2022년에 SHA-1을 2030년 말까지 퇴출하겠다고 발표했어요.

그럼 Git은 왜 아직 SHA-1을 쓸까

Git 커밋 ID는 40자 SHA-1이에요. Git은 SHAttered 직후 충돌 공격 패턴을 감지하는 "hardened SHA-1"으로 바꿨고, 저장소를 SHA-256으로 만드는 옵션(git init --object-format=sha256)도 실험 기능으로 들어가 있어요. 다만 기존 생태계와의 호환 문제로 기본값은 아직 SHA-1이에요.

광고
광고

비밀번호 저장에 SHA-256을 쓰면 안 되는 이유

여기서 많이들 헷갈려요. SHA-256은 안전한 해시인데 왜 비밀번호에는 쓰면 안 될까요? 이유는 너무 빨라서예요. 해시는 원래 빠를수록 좋은 함수인데, 비밀번호에서는 그게 공격자에게 유리해요. DB가 유출되면 공격자는 후보 비밀번호를 하나씩 해시해서 대조하는데, 1초에 몇 번을 시도할 수 있느냐가 곧 뚫리는 속도거든요.

GPU 1장으로 1초에 시도할 수 있는 해시 계산 수
MD5MD5 · 1,641억 회/초1,641억 회/초SHA-1SHA-1 · 506억 회/초506억 회/초SHA-256SHA-256 · 220억 회/초220억 회/초

같은 벤치마크에서 bcrypt(cost 5)는 초당 약 18만 회예요. SHA-256보다 10만 배 이상 느려서 막대로는 보이지도 않아요.

단위: 억 회/초 · 자료: hashcat 공개 벤치마크(RTX 4090 1장) 기준 근삿값
표로 보기
구분초당 계산
MD51,641
SHA-1506
SHA-256220

비밀번호 전용 해시는 일부러 느리고, 메모리를 많이 쓰게 만들어서 이 속도를 떨어뜨려요.

방식특징권장 설정 예 (OWASP 기준)
Argon2id2015년 비밀번호 해싱 대회 우승. 메모리를 많이 써서 GPU 병렬 공격에 강함메모리 19MiB, 반복 2, 병렬 1
bcrypt1999년 발표. 가장 널리 지원됨. 입력 72바이트까지만 사용cost 10 이상
scrypt메모리 비용을 조절 가능N=2¹⁷, r=8, p=1
PBKDF2FIPS 인증이 필요한 환경용HMAC-SHA256으로 60만 회 반복

이 함수들은 솔트(salt)도 자동으로 붙여 줘요. 솔트는 사용자마다 다른 랜덤 값이라, 같은 비밀번호 1234 를 쓴 두 사람도 저장되는 해시가 달라져요. 그래서 레인보우 테이블이 통하지 않고, 공격자는 사용자 한 명씩 따로 계산해야 해요. bcrypt 결과 $2b$12$… 에는 알고리즘, cost(12), 솔트, 해시가 한 문자열에 다 들어 있어서 따로 솔트 칸을 만들 필요도 없어요.

비밀번호 길이가 왜 중요한지, 몇 자리면 무차별 대입에 몇 년이 걸리는지는 비밀번호 엔트로피와 무차별 대입 시간 글에서 계산해 두었어요.

HMAC, 키가 들어간 해시로 위변조 막기

웹훅이나 API 요청이 정말 상대방이 보낸 건지 확인하려면 해시만으로는 부족해요. 요청을 가로챈 사람도 본문을 고친 뒤 SHA-256을 다시 계산해서 붙이면 그만이니까요. 그래서 서로만 아는 비밀 키를 섞어 해시하는 HMAC을 써요.

import hmac, hashlib

secret = b"secret"
body = b"hello"
sig = hmac.new(secret, body, hashlib.sha256).hexdigest()
# 88aab3ede8d3adf94d26ab90d3bafd4a2083070c3bcce9c014ee04a443847c0b

# 검증할 땐 == 대신 상수 시간 비교
hmac.compare_digest(sig, received_sig)

GitHub 웹훅의 X-Hub-Signature-256 헤더, 결제 대행사의 콜백 서명, JWT의 HS256 서명이 모두 HMAC-SHA256이에요. JWT 서명이 어떻게 만들어지는지는 JWT 구조와 서명 원리 글에 자세히 있어요.

HMAC을 직접 흉내 내서 SHA256(키 + 메시지) 로 만들면 안 돼요. SHA-256 같은 구조의 해시는 길이 확장 공격에 약해서, 키를 몰라도 원래 해시값과 메시지 길이만 알면 뒤에 내용을 덧붙인 메시지의 올바른 해시를 계산할 수 있거든요. HMAC은 키를 안쪽·바깥쪽으로 두 번 섞는 구조(RFC 2104)라서 이 문제가 없어요. 그리고 서명을 비교할 땐 일반 == 대신 hmac.compare_digest 같은 상수 시간 비교를 써야 앞 글자부터 맞혀 나가는 타이밍 공격을 피할 수 있어요.

광고
광고

상황별로 어떤 해시를 쓸까

상황추천피할 것
다운로드 파일 무결성SHA-256 (+ GPG 서명)MD5, SHA-1
비밀번호 저장Argon2id, bcryptSHA-256, MD5 (솔트를 붙여도)
API·웹훅 서명HMAC-SHA256SHA256(키+메시지)
캐시 키·중복 제거 (공격자 없음)MD5, SHA-1, xxHash도 가능—
전자 서명·인증서SHA-256 이상SHA-1
랜덤 토큰 생성암호학적 난수(crypto)시각이나 ID를 해시한 값

마지막 줄도 자주 하는 실수예요. md5(user_id + 현재시각) 으로 만든 재설정 토큰은 입력을 추측해 똑같이 계산할 수 있어요. 토큰은 secrets.token_urlsafe() 같은 난수로 만드세요.

자주 묻는 질문

해시값으로 원래 문자열을 복호화할 수 있나요?

수학적으로 되돌리는 방법은 없어요. 다만 "1234", "password"처럼 흔한 입력은 미리 계산해 둔 표와 대조하면 금방 찾아져요. 온라인 "MD5 복호화" 사이트가 하는 일이 바로 이 대조예요. 그래서 짧거나 흔한 값을 해시한 결과는 사실상 공개된 것과 같아요.

MD5와 SHA-256 중 무엇이 더 빠른가요?

일반적으로 MD5가 더 빨라요. GPU 벤치마크에서도 MD5가 SHA-256보다 7배쯤 빠르게 나와요. 하지만 파일 체크섬 정도면 둘 다 디스크 읽기 속도가 병목이라 체감 차이가 거의 없으니, 보안이 걸린 곳에선 SHA-256을 쓰세요.

같은 파일인데 체크섬이 다르게 나와요.

먼저 알고리즘이 같은지(길이로 확인), 다운로드가 끝까지 됐는지(파일 크기 비교) 보세요. 텍스트 파일이라면 줄바꿈(CRLF와 LF)이나 BOM 차이로 바이트가 달라졌을 수 있어요. 그래도 다르면 다른 미러에서 다시 받고, 계속 다르면 그 파일은 쓰지 않는 게 안전해요.

비밀번호를 SHA-256으로 두 번, 천 번 해시하면 안전해지나요?

조금 느려지긴 하지만 직접 만든 방식은 솔트·반복 횟수·비교에서 실수가 나기 쉬워요. 이미 검증된 Argon2id나 bcrypt 라이브러리를 쓰는 게 정답이에요. 반복 방식이 꼭 필요하면 표준인 PBKDF2를 쓰세요.

한글 문자열을 해시하면 왜 사이트마다 결과가 다른가요?

해시는 글자가 아니라 바이트를 계산하기 때문이에요. 같은 "안녕"도 UTF-8과 EUC-KR은 바이트가 달라서 해시가 달라져요. UTF-8 기준 "안녕"의 SHA-256은 e8f817f3…으로 시작해요. 앞뒤 공백이나 줄바꿈이 섞여도 결과가 바뀌니 입력부터 확인하세요.

정리

해시는 되돌릴 수 없는 고정 길이 지문이고, 암호화는 키로 되돌리는 잠금, 인코딩은 누구나 되돌리는 형식 변환이에요. MD5(32자)와 SHA-1(40자)은 각각 2004년과 2017년 SHAttered로 실제 충돌이 만들어져 서명·인증서·위변조 검사에는 쓰면 안 되고, 지금 기본은 SHA-256(64자)이에요. 다운로드 파일은 certutil·shasum -a 256·sha256sum 으로 전체 값을 대조하세요.

비밀번호는 빠른 해시 대신 솔트가 자동으로 붙는 Argon2id·bcrypt로, API 서명은 HMAC-SHA256으로 만들면 돼요. 문자열의 MD5·SHA-1·SHA-256 값을 바로 비교해 보려면 해시 생성기를, 강한 비밀번호가 필요하면 비밀번호 생성기를 써 보세요. 해시값을 2진수·16진수로 뜯어보고 싶다면 2진수 16진수 변환 원리 글도 같이 보면 좋아요.

#MD5 SHA256 차이#해시 암호화 차이#체크섬 확인 방법#SHA-1 충돌 SHAttered#비밀번호 해시 bcrypt Argon2#HMAC 원리#sha256sum certutil#해시 함수란
← 이전 글CSV 엑셀 한글 깨짐 해결, UTF-8 BOM·CP949·따옴표 규칙 정리다음 글 →HTML 엔티티 < &   뜻과 이스케이프·XSS 방어
광고

더 둘러보기

💻 개발자 다른 도구

🔥 많이 찾는 도구

🔮 재미로 한 번 더

📝 읽어 볼 만한 글

글 전체 보기 →