해싱은 임의 크기의 데이터를 고정 길이 문자열로 변환하는 프로세스로, 무결성 검증과 안전한 비밀번호 저장에 사용됩니다. OWASP(Open Web Application Security Project, 2025)에 따르면, 해시 함수의 올바른 사용은 자격 증명 유출과 관련된 취약점의 최대 70%를 방지합니다. 암호화 해시는 디지털 서명, 블록체인 기술 및 버전 관리의 기초를 이룹니다.
주요 내용
해싱은 입력 데이터의 임의 집합을 다이제스트 또는 해시 값이라고 하는 고정 길이 비트 문자열로 변환하는 해시 함수를 계산하는 프로세스입니다. 암호화와 달리 해싱은 단방향 프로세스입니다: 해시에서 원본 데이터를 복구하는 것은 불가능합니다.
암호화 해시 함수는 네 가지 필수 속성을 가집니다: 결정론성(동일한 입력은 항상 동일한 해시를 생성), 비가역성(해시에서 입력을 복구하는 것이 계산적으로 불가능), 눈사태 효과(입력의 1비트 변경은 평균적으로 해시 비트의 절반을 변경), 충돌 저항성(동일한 해시를 가진 두 개의 다른 입력을 찾는 것이 계산적으로 불가능).
해싱과 암호화의 차이를 이해하는 것이 중요합니다. 암호화는 양방향 프로세스입니다: 암호화된 데이터는 키를 사용하여 복호화할 수 있습니다. 해싱은 단방향 프로세스입니다: 변환 후 데이터를 복구할 수 없습니다. 이 속성은 해싱을 비밀번호 저장에 이상적으로 만듭니다: 시스템은 해시만 저장하며, 데이터베이스가 유출되더라도 비밀번호는 보호된 상태로 유지됩니다.
모든 해시 함수가 보안 작업에 동등하게 적합한 것은 아닙니다. 암호화와 비암호화 범주로의 구분은 모바일 개발에서 특정 작업을 위한 알고리즘을 선택할 때 매우 중요합니다.
이 함수들은 무차별 대입 공격을 어렵게 만들기 위해 의도적으로 느리고 복잡합니다. 충돌 및 원상 공격에 저항해야 합니다. SHA-2 제품군(SHA-224, SHA-256, SHA-384, SHA-512)은 NIST의 인증을 받았으며 정부 시스템에서 사용하도록 권장됩니다. 비밀번호 해싱을 위해 bcrypt, scrypt 및 Argon2 알고리즘이 조정 가능한 복잡도로 추가로 사용됩니다.
이 함수들은 보안이 아닌 속도에 최적화되어 있습니다. 예: CityHash, MurmurHash, xxHash. 해시 테이블, 데이터 중복 제거 및 중요하지 않은 데이터의 빠른 무결성 검증을 위한 체크섬에 사용됩니다. 비밀번호 저장이나 디지털 서명 검증에 절대 사용하지 않는 것이 중요합니다 — 빠른 속도로 인해 무차별 대입 공격에 취약해집니다.
| 유형 | 예시 | 응용 분야 |
|---|---|---|
| 암호화 | SHA-256, SHA-3, bcrypt | 비밀번호, 서명, TLS |
| 비암호화 | MurmurHash, xxHash | 해시 테이블, 캐시 |
| 비밀번호 KDF | bcrypt, scrypt, Argon2 | 비밀번호 저장 |
현대 모바일 개발에서 사용되는 가장 일반적인 해싱 알고리즘을 살펴보겠습니다. 각각 장단점이 있습니다.
SHA-256은 현대 암호화의 상징이며, FIPS 180-4 표준의 일부로 NIST에서 권장합니다. 이 알고리즘은 256비트 다이제스트를 생성하며 TLS 프로토콜, 블록체인 네트워크 및 버전 관리 시스템의 핵심 구성 요소입니다. NCC Group(2025)의 보고서에 따르면, SHA-256은 인증서 투명성 서명을 위해 TLS 인증서의 96%에서 사용됩니다.
SHA-3은 해시 함수의 최신 제품군으로, 2015년에 FIPS 202로 NIST에 의해 표준화되었습니다. Merkle–Damgård 구조로 구축된 SHA-2와 달리 SHA-3은 스펀지 함수를 사용하는 다른 Keccak 구조를 기반으로 합니다. 이로 인해 SHA-3은 향후 SHA-2에 대해 발생할 수 있는 공격에 저항력을 가집니다. 모바일 개발자의 경우 SHA-3은 Android 7.0 및 iOS 13부터 표준 암호화 라이브러리를 통해 사용할 수 있습니다.
import java.security.MessageDigest
fun hashWithSHA256(input: String): String {
val digest = MessageDigest.getInstance("SHA-256")
val hashBytes = digest.digest(input.toByteArray())
return hashBytes.joinToString("") { String.format("%02x", it) }
}
범용 암호화 해시는 비밀번호 저장에 충분하지 않습니다 — 너무 빠릅니다. bcrypt는 비밀번호 해싱을 위해 특별히 설계되었습니다: 솔트와 계산 시간을 조절하는 비용 매개변수가 포함되어 있습니다. 비용을 두 배로 늘리면 해싱 시간이 두 배가 되어 강력한 하드웨어에서도 무차별 대입이 비효율적이 됩니다.
import at.favre.lib.crypto.bcrypt.BCrypt
fun hashPassword(password: String): String {
return BCrypt.create()
.hashToString(BCrypt.MIN_COST, password.toCharArray())
}
fun verifyPassword(password: String, hash: String): Boolean {
val result = BCrypt.verifyer().verify(password.toCharArray(), hash)
return result.verified
}
Argon2는 Password Hashing Competition(2015)의 우승자이며, OWASP에서 비밀번호 해싱을 위한 최고의 선택으로 권장합니다. Argon2id는 부채널 공격 및 시간-메모리 트레이드오프 공격에 저항하는 변종입니다. bcrypt와 달리 Argon2는 실행 시간, 메모리 사용량 및 병렬 처리 정도를 별도로 구성할 수 있어 다양한 유형의 공격에 대해 유연한 보호를 제공합니다.
해싱은 사용자 인증부터 다운로드된 파일의 무결성 검증까지 모바일 개발의 많은 실용적인 작업을 해결합니다. 주요 사용 사례를 살펴보겠습니다.
주요 사용 사례는 서버 측에서의 안전한 비밀번호 저장입니다. 등록 시 애플리케이션은 비밀번호를 서버로 보내고, 서버에서는 bcrypt 또는 Argon2를 사용하여 솔트와 함께 해싱한 후 데이터베이스에 저장합니다. 로그인 시 서버는 입력된 비밀번호를 해싱하여 저장된 해시와 비교합니다. OWASP는 Argon2id를 다음 매개변수로 사용할 것을 권장합니다: 시간 2초, 메모리 64MB, 병렬 처리 정도 4.
OBB 패키지나 콘텐츠 업데이트와 같은 대용량 파일을 다운로드할 때 모바일 애플리케이션은 해싱을 통해 무결성을 검증할 수 있습니다. 서버는 파일의 SHA-256 해시를 게시하고, 애플리케이션은 다운로드된 데이터의 해시를 계산하여 비교합니다. 이를 통해 전송 중 파일이 손상되거나 변조되지 않았음을 보장합니다. Google Play Console(2025)에 따르면, 인증된 애플리케이션의 해시 검증은 손상된 다운로드 공격의 최대 99.9%를 방지합니다.
해시는 효율적인 캐시 및 데이터 중복 제거 구축에 적극적으로 사용됩니다. 이미지나 JSON 응답의 주소가 해싱되어 캐시 키로 사용됩니다: 반복 요청 시 시스템은 해시를 비교하고 데이터가 변경되지 않은 경우 저장된 결과를 반환합니다. 이 작업에는 MurmurHash 또는 xxHash와 같은 비암호화 해시 함수가 적합하며 최대 성능을 제공합니다.
import java.security.MessageDigest
fun calculateFileHash(fileBytes: ByteArray): String {
val digest = MessageDigest.getInstance("SHA-256")
val hash = digest.digest(fileBytes)
return hash.joinToString("") { String.format("%02x", it) }
}
fun verifyIntegrity(data: ByteArray, expectedHash: String): Boolean {
val actualHash = calculateFileHash(data)
return actualHash == expectedHash
}
숙련된 개발자라도 해싱 작업 시 실수를 합니다. 암호화 보호의 모든 이점을 무효화할 수 있는 가장 일반적인 문제를 살펴보겠습니다.
MD5와 SHA-1은 실용적인 충돌 공격이 존재하는 구식 알고리즘입니다. MD5는 2004년 중국 연구자 그룹에 의해 깨졌습니다(1시간 만에 충돌). SHA-1은 2017년 Google과 Centrum Wiskunde & Informatica 팀에 의해 깨졌습니다(SHAttered 공격). 새 프로젝트에서 이러한 알고리즘을 사용하는 것은 OWASP 분류에 따라 심각한 보안 오류로 간주됩니다.
솔트 없이 비밀번호를 해싱하는 것은 심각한 취약점입니다. 솔트는 각 사용자에게 고유한 임의 문자열로, 해싱 전에 비밀번호에 추가됩니다. 솔트가 없으면 두 개의 동일한 비밀번호가 동일한 해시를 생성하여 레인보우 테이블을 사용한 크래킹이 가능합니다. OWASP는 각 사용자에 대해 개별적으로 생성되는 최소 32바이트의 암호학적으로 강력한 솔트 사용을 권장합니다.
bcrypt나 Argon2를 사용하더라도 너무 낮은 비용 매개변수를 선택하면 보호 수준이 낮아질 수 있습니다. OWASP(2025)에 따르면 bcrypt 반복의 최소 횟수는 10(2^10 = 1024회 반복)이어야 하며, Argon2id의 경우 대상 플랫폼에서 계산 시간이 최소 1초여야 합니다. 너무 낮은 매개변수는 GPU 팜에서 무차별 대입 공격을 실질적으로 가능하게 만듭니다.
자주 묻는 질문
해싱은 결과를 원본 데이터로 되돌릴 수 없는 단방향 프로세스입니다. 암호화는 양방향 프로세스입니다: 암호화된 데이터는 키를 사용하여 복호화할 수 있습니다. 해싱은 비밀번호 저장 및 무결성 검증에 사용되며, 암호화는 클라이언트와 서버 간 데이터의 기밀 전송에 사용됩니다.
OWASP는 GPU 및 부채널 공격에 대한 구성 가능한 보호 기능으로 인해 비밀번호 해싱에 가장 적합한 선택으로 Argon2id를 권장합니다. 대안: bcrypt(검증되었고 구성이 쉬움), scrypt(ASIC 공격에 강함) 및 PBKDF2. SHA-256과 SHA-512는 비밀번호에 적합하지 않습니다 — 너무 빠르며 대규모 무차별 대입 공격으로부터 보호하지 못합니다.
충돌은 두 개의 다른 입력 데이터 세트가 동일한 해시를 생성하는 상황입니다. 암호화 해시 함수의 경우 충돌을 찾는 것이 계산적으로 불가능해야 합니다. 예를 들어, 두 개의 임의 메시지에 대한 SHA-256 충돌 확률은 약 2^128분의 1입니다 — 이는 극히 작은 값입니다.
아니요, bcrypt는 자체 알고리즘에 자동으로 솔트를 포함합니다. BCrypt.hashToString()을 호출하면 라이브러리가 암호학적으로 강력한 16바이트 솔트를 생성하여 해시 및 비용 매개변수와 함께 출력 문자열에 포함시킵니다. scrypt와 Argon2도 유사하게 작동합니다. 이것이 전문가들이 비밀번호 보호를 위해 범용 해시 함수 대신 특수 KDF 사용을 권장하는 이유 중 하나입니다.
네, 해시는 파일의 허용 목록 및 차단 목록을 만드는 데 사용됩니다. 안티바이러스 데이터베이스에는 알려진 악성 프로그램의 해시가 포함되어 있습니다. 그러나 공격자는 프로그램에서 1바이트를 변경할 수 있으며, 이렇게 하면 해시가 완전히 변경됩니다. 따라서 최신 시스템은 정확한 일치뿐만 아니라 의미적으로 유사한 파일을 찾는 퍼지 해싱(SSDeep, TLSH)을 사용합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.