(CS/컴퓨터공학) 해시 vs 암호학적 해시, 그리고 왜 모두가 SHA-256을 쓰는가
✨ 개요
“해시(hash)”는 임의 길이 입력 → 고정 길이 출력으로 매핑하는 함수입니다.
그중 암호학적 해시(Cryptographic Hash) 는 보안을 위해 더 강력한 성질을 요구합니다. 이 글은 두 개념의 차이와 SHA-256이 표준으로 자리 잡은 이유를 정리했습니다.
1. 한 장 요약
- 일반 해시: 빠르고 균등한 분포가 목적(해시테이블, 파티셔닝).
- 암호학적 해시: 보안 성질(역상·2차역상·충돌 내성 + 어발랜치)이 필수.
- SHA-256: 널리 검증된 표준(256비트 출력, 충돌 난이도 ≈ 2^128)로 무결성·서명·블록체인·HMAC 등 핵심 인프라에 사용.
- 비밀번호 해싱엔 SHA-256 단독 사용 금지 → bcrypt/scrypt/Argon2.
2 해시 vs 암호학적 해시: 무엇이 다른가?
| 구분 | 일반 해시(Murmur3, xxHash 등) | 암호학적 해시(SHA-256, SHA-3, BLAKE2/3) |
|---|---|---|
| 목적 | 속도·균등 분포 | 보안 성질 + 균등성 |
| 역상 내성(Preimage) | 요구 X | 요구 O: h만으로 x 찾기 매우 어려움 |
| 2차 역상 내성(Second Preimage) | 요구 X | 요구 O: 같은 h를 만드는 x′ 찾기 어려움 |
| 충돌 내성(Collision) | 낮음/신경 안 씀 | 요구 O: x≠x′인데 H(x)=H(x′) 찾기 어려움 |
| 어발랜치(Avalanche) | 있으면 좋음 | 강하게 요구(1비트 변화 → 출력 절대적 변화) |
| 사용처 | 해시맵 키, 샤딩, 체크섬 | 무결성, 전자서명, HMAC, 블록체인, 증명 |
결론: 보안이 관여하면 반드시 암호학적 해시를 사용해야 합니다.
3 SHA-256 한눈에
- 출력 길이: 256비트(32바이트, 보통 64자리 16진수로 표시)
- 안전도 직관
- 충돌 탐색(생일 한계): 대략 2^128 시도 필요
- 역상 탐색: 2^256 시도 필요
- 구조/비고: SHA-2 계열(Merkle–Damgård). 길이 확장 공격에 주의 → MAC은 HMAC-SHA-256 사용.
- 표준/보급: NIST 표준, 대부분의 CPU/라이브러리에서 고속 구현(심지어 일부 하드웨어 가속).
4. 어디에 쓰이나? (대표 시나리오)
1) 무결성 검증
- 파일 배포 시 SHA256SUM 제공 → 사용자는 다운로드 후 해시 일치로 위·변조 탐지.
2) 전자서명/PKI
- 서명은 보통 메시지를 먼저 해시(SHA-256) 하고 해시값에 서명 → 속도↑, 일관성↑.
3) HMAC-SHA-256
- API 요청 서명, 웹훅 검증 등 메시지 인증(변조 방지 + 키 필요).
4) 블록체인/머클트리/PoW
- 블록 해시, 트랜잭션 머클루트, 비트코인 PoW 등 합의·무결성의 근간.
5) 콘텐츠 주소화(CID)
- 동일 내용이면 동일 주소(해시) → 중복 제거, 캐싱 최적화.
5. 체크섬 vs 암호학적 해시
- 체크섬(Adler-32, CRC32): 우발적 오류(전송·디스크 비트에러) 탐지에 적합.
- 암호학적 해시(SHA-256): 의도적 공격자까지 고려(위·변조/위조 방지).
→ 보안 목적이면 체크섬만으로는 불충분.
6. 비밀번호에는 왜 쓰면 안 되나?
- SHA-256은 너무 빠름 → GPU/ASIC 대입 공격에 취약.
- 권장: bcrypt / scrypt / Argon2id(느리고 메모리 집약적) + Salt(+ 필요 시 Pepper).
- 단, 패스워드 저장 외 용도(무결성·서명·HMAC 등)에는 SHA-256이 매우 적합.
7. 실무 주의사항(함정과 베스트 프랙티스)
- 길이 확장 공격 회피: 임의 MAC 구현 금지 → HMAC-SHA-256 사용.
- 짧게 자른 해시: 표기 간편화로 8~16자리만 쓰면 충돌 위험 급증(생일 역설).
- Salt 없는 해시: 동일 비밀번호의 동일 해시 발생 → 레인보우 테이블 공격에 취약.
- SHA-1 금지: 알려진 충돌 공격 존재.
- 대안 고려: SHA-3/Keccak, BLAKE3(고속) — 표준/호환성 요구가 낮을 때.
8. 빠른 사용 예시
8.1 Kotlin/JVM (HMAC-SHA-256 포함)
import java.security.MessageDigest
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
fun sha256Hex(bytes: ByteArray): String =
MessageDigest.getInstance("SHA-256").digest(bytes).joinToString("") { "%02x".format(it) }
fun hmacSha256Hex(key: ByteArray, data: ByteArray): String {
val mac = Mac.getInstance("HmacSHA256")
mac.init(SecretKeySpec(key, "HmacSHA256"))
return mac.doFinal(data).joinToString("") { "%02x".format(it) }
}
9. 선택 가이드
- 무결성/서명/HMAC/블록체인: SHA-256 권장(범용·호환성 최고).
- 비밀번호 저장: Argon2id/bcrypt/scrypt(절대 SHA-256 단독 X).
- 최신/고속 필요: SHA-3 또는 BLAKE3(요구사항·호환성 검토).
- 체크섬 목적: CRC32/XXH3(비보안) + 중요 구간은 SHA-256로 이중 확인.