SHA-1 해시 생성기
임의의 텍스트에서 SHA-1 해시 생성
입력 텍스트
SHA-1 해시
SHA-1 해시가 여기에 표시됩니다…
SHA-1 해싱이란 무엇입니까?
SHA-1(Secure Hash Algorithm 1)은 모든 입력에서 고정된 160비트(20바이트) 다이제스트를 생성하는 암호화 해시 함수입니다. NSA가 개발하고 NIST가 1995년 FIPS PUB 180-1로 표준화했으며, 이후 RFC 3174에 문서화된 SHA-1은 SHA-0과 MD5의 더 강력한 후속 알고리즘으로 설계되었습니다. 이 알고리즘은 512비트 블록 단위로 입력을 처리하며, 80라운드의 비트 연산을 통해 40자 16진수 지문을 생성합니다. 이 지문은 10년 이상 SSL/TLS, PGP, SSH, IPsec의 핵심으로 사용되었습니다.
모든 암호화 해시 함수와 마찬가지로 SHA-1은 단방향 변환입니다. 입력에서 해시를 계산하는 것은 빠르지만, 해시만으로 원래 입력을 복구하는 것은 계산상 불가능합니다. 입력의 단 1비트 변경만으로도 완전히 다른 160비트 다이제스트가 생성됩니다. 이를 눈사태 효과(avalanche effect)라고 합니다. SHA-1은 무한히 큰 입력 공간을 고정된 160비트 출력으로 매핑하므로, 서로 다른 두 입력이 동일한 해시를 생성하는 충돌(collision)은 수학적으로 반드시 존재합니다. 안전한 해시 함수의 보안 요건은 이러한 충돌을 찾는 데 출력 비트 길이의 절반에 해당하는 약 2^80번의 연산이 필요해야 한다는 것입니다.
2017년 Google과 CWI 암스테르담은 SHAttered 공격을 공개하며, 서로 다른 두 PDF 파일이 동일한 다이제스트를 갖도록 만드는 최초의 실용적 SHA-1 충돌을 입증했습니다. 이 공격에는 약 2^63.1번의 SHA-1 연산이 필요했으며, 이는 이론적 한계인 2^80을 크게 밑도는 수치입니다. 2020년에는 Gaetan Leurent와 Thomas Peyrin이 약 2^63.4번의 연산으로 선택 접두사 충돌 공격 비용을 추가로 낮췄습니다. 그 결과, 모든 주요 브라우저, 인증 기관, 표준 기관은 디지털 서명과 TLS 인증서에서 SHA-1 지원을 중단했습니다. 그러나 SHA-1은 비보안 목적으로는 여전히 사용됩니다. Git 객체 ID(단, Git은 SHA-256으로 이전 중), 레거시 HMAC 구성, 그리고 적대적 충돌 저항성이 필요 없는 파일 무결성 체크섬에서 계속 활용됩니다.
이 SHA-1 생성기를 사용하는 이유
아무것도 설치하거나 코드를 작성하지 않고 즉시 SHA-1 해시를 생성합니다. 텍스트를 붙여넣으면 40자 16진수 다이제스트가 실시간으로 표시됩니다. 레거시 체크섬 검증, Git 내부 디버깅, 또는 해시 기반 워크플로우 테스트에 유용합니다.
SHA-1 활용 사례
SHA-1과 다른 해시 알고리즘 비교
SHA-1은 160비트 다이제스트를 생성합니다 — MD5(128비트)보다 길지만 SHA-2 계열 알고리즘보다는 현저히 짧습니다. 아래 표는 각 알고리즘의 다이제스트 크기, 표준, 적합한 활용 사례를 비교합니다.
| 알고리즘 | 다이제스트 크기 | 16진수 길이 | 표준 | 최적 용도 |
|---|---|---|---|---|
| SHA-1 | 160 bits | 40 hex chars | 1995 / RFC 3174 | Deprecated — legacy git commits, old TLS |
| SHA-256 | 256 bits | 64 hex chars | 2001 / FIPS 180-4 | TLS certificates, blockchain, JWTs |
| SHA-384 | 384 bits | 96 hex chars | 2001 / FIPS 180-4 | Government systems, higher security margin |
| SHA-512 | 512 bits | 128 hex chars | 2001 / FIPS 180-4 | Digital signatures, HMAC with large keys |
| MD5 | 128 bits | 32 hex chars | 1992 / RFC 1321 | Checksums only — broken since 2004 |
| SHA-3 | 256 bits | 64 hex chars | 2015 / FIPS 202 | Post-quantum readiness, alternative to SHA-2 |
| BLAKE3 | 256 bits | 64 hex chars | 2020 | High-performance checksums, Merkle trees |
SHA-1의 동작 원리
SHA-1은 Merkle-Damgård 구조를 따릅니다. 메시지는 패딩 처리되어 512비트 블록으로 분할되고, 각 블록은 해당 블록에서 파생된 메시지 스케줄과 입력을 혼합하는 80라운드의 비트 연산을 거칩니다. 다섯 개의 32비트 상태 워드(H0부터 H4)가 현재 해시 상태를 유지하며, 이 워드들의 최종 연결이 160비트 다이제스트를 생성합니다.
SHA-1: 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
(160 bits = 20 bytes = 40 hex characters)
| 단계 | 설명 |
|---|---|
| Padding | Append a 1-bit, then zeros, until message length is 448 mod 512. Append the original length as a 64-bit big-endian integer. |
| Block splitting | Divide the padded message into 512-bit (64-byte) blocks. |
| Expansion | Expand each 16-word block into 80 words using a left-rotate-by-1 XOR feedback schedule. |
| Compression | Process 80 rounds per block using four nonlinear functions (Ch, Parity, Maj, Parity) across rounds 0-19, 20-39, 40-59, and 60-79. |
| Output | Concatenate the five 32-bit state words (H0-H4) into a 160-bit (20-byte) digest, rendered as 40 hexadecimal characters. |
SHA-1과 MD5의 핵심 차이는 상태 워드 수(5개 대 4개), 블록당 라운드 수(80개 대 64개), 그리고 왼쪽 회전 피드백을 포함한 메시지 스케줄 사용입니다. 이러한 차이점으로 SHA-1은 더 큰 출력(160비트 대 128비트)을 제공하고 원래 더 높은 보안 여유를 제공했지만, 두 알고리즘 모두 현재 충돌 저항성이 취약한 것으로 간주됩니다.
코드 예제
인기 있는 언어 및 환경에서 SHA-1 해시를 생성하는 방법입니다. MD5와 달리 SHA-1은 브라우저 Web Crypto API에서 사용할 수 있어 브라우저와 Node.js 환경 모두에서 외부 라이브러리 없이 사용 가능합니다.
// SHA-1 is available in the Web Crypto API
async function sha1(text) {
const data = new TextEncoder().encode(text)
const hashBuffer = await crypto.subtle.digest('SHA-1', data)
const hashArray = Array.from(new Uint8Array(hashBuffer))
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
}
await sha1('hello world')
// → "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
// Node.js (built-in crypto module)
const crypto = require('crypto')
crypto.createHash('sha1').update('hello world').digest('hex')
// → "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"import hashlib
# Basic SHA-1 hash
result = hashlib.sha1(b'hello world').hexdigest()
print(result) # → "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
# Hash a string (encode to bytes first)
text = 'hello world'
hashlib.sha1(text.encode('utf-8')).hexdigest()
# → "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"
# Hash a file in chunks
with open('file.bin', 'rb') as f:
sha1 = hashlib.sha1()
for chunk in iter(lambda: f.read(8192), b''):
sha1.update(chunk)
print(sha1.hexdigest())package main
import (
"crypto/sha1"
"fmt"
)
func main() {
data := []byte("hello world")
hash := sha1.Sum(data)
fmt.Printf("%x\n", hash)
// → 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed
}# Using sha1sum (Linux) or shasum (macOS) echo -n "hello world" | sha1sum # → 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed - # macOS echo -n "hello world" | shasum -a 1 # → 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed - # Hash a file sha1sum package.json # → a1b2c3d4e5f6... package.json # Using openssl (cross-platform) echo -n "hello world" | openssl sha1 # → SHA1(stdin)= 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed