Toolypet
블로그로 돌아가기
Security

SHA-256 vs bcrypt vs Argon2 - 개발자를 위한 해싱 알고리즘 완벽 비교

비밀번호 저장에 SHA-256을 쓰면 안 되는 이유, bcrypt와 Argon2의 차이, 2026년 권장 해싱 전략을 상세히 알아봅니다.

Toolypet Team

Toolypet Team

Development Team

7 분 읽기

SHA-256 vs bcrypt vs Argon2: 언제 무엇을 사용해야 할까?

"비밀번호를 SHA-256으로 해싱해서 저장하면 안전하겠지?"

이 질문을 하는 개발자가 많습니다. 결론부터 말하면, 비밀번호에 SHA-256을 사용하면 안 됩니다.

이 가이드에서는 해싱 알고리즘의 차이와 각 상황에 맞는 올바른 선택을 알아봅니다.


해싱 vs 암호화: 기본 개념

해싱 (Hashing)

입력 → 해시 함수 → 고정 길이 출력 (복원 불가)

"password" → SHA-256 → "5e884898da28047d..."
  • 단방향: 원본 복구 불가능
  • 결정적: 같은 입력 = 같은 출력
  • 고정 길이: 입력 크기와 무관하게 일정한 출력

암호화 (Encryption)

입력 + 키 → 암호화 → 암호문 → 복호화 + 키 → 원본

"password" + key → AES → "Xyz..." → AES + key → "password"
  • 양방향: 키로 원본 복구 가능
  • 키 의존: 키가 없으면 복호화 불가

비밀번호 저장에는 해싱을 사용합니다. 원본을 알 필요 없이 입력값과 해시를 비교하면 됩니다.


해싱 알고리즘 분류

빠른 해시 (Fast Hash)

알고리즘출력 길이속도용도
MD5128비트매우 빠름❌ 보안용 사용 금지
SHA-1160비트빠름❌ 보안용 사용 금지
SHA-256256비트빠름파일 무결성, 디지털 서명
SHA-512512비트빠름파일 무결성, 블록체인

느린 해시 (Slow Hash / Password Hash)

알고리즘특징2026 권장
bcrypt시간 조절 가능 (cost)
scrypt메모리 집약적
Argon2최신, OWASP 1순위✅✅
PBKDF2호환성 높음⚠️ 레거시

왜 SHA-256으로 비밀번호를 저장하면 안 될까?

이유 1: 너무 빠르다

SHA-256은 속도를 위해 설계되었습니다. 이것이 파일 무결성 검사에는 장점이지만, 비밀번호 저장에는 치명적 단점입니다.

현대 GPU 성능:
- MD5: 1,800억 해시/초
- SHA-256: 100억 해시/초
- bcrypt (cost 12): 1,000 해시/초

8자리 복잡한 비밀번호도 SHA-256으로 저장하면 몇 분 만에 크래킹됩니다.

이유 2: Salt 직접 관리 필요

# ❌ 잘못된 방법
hash = sha256(password)

# 문제: Rainbow Table 공격에 취약

# ⚠️ 개선했지만 여전히 부족
salt = generate_random_salt()
hash = sha256(salt + password)

# 문제: 여전히 너무 빠름

이유 3: GPU 가속 취약

SHA-256은 GPU에서 병렬 처리가 쉽습니다. 공격자는 게이밍 GPU 몇 개로 엄청난 속도로 해시를 계산할 수 있습니다.


bcrypt: 27년 검증된 표준

작동 원리

bcrypt(cost, salt, password) → hash

cost: 계산 반복 횟수 (2^cost)
salt: 22자 랜덤 문자열 (자동 생성)

왜 bcrypt가 안전한가?

  1. 의도적으로 느림: cost factor로 속도 조절
  2. 자동 Salt: 매번 다른 해시 생성
  3. 메모리 집약: GPU 가속 어려움

Cost Factor 가이드 (2026)

Cost해시 시간권장 용도
10~100ms개발/테스트
12~250ms일반 웹앱 (권장)
13-14~500ms높은 보안 요구
15+1초+특수 목적

코드 예시

// Node.js with bcrypt
const bcrypt = require('bcrypt');

// 해싱 (회원가입)
const hash = await bcrypt.hash(password, 12); // cost 12

// 검증 (로그인)
const isValid = await bcrypt.compare(inputPassword, storedHash);
# Python with bcrypt
import bcrypt

# 해싱
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))

# 검증
is_valid = bcrypt.checkpw(input_password.encode(), stored_hash)

Argon2: 차세대 표준

Argon2란?

2015년 Password Hashing Competition 우승자입니다. OWASP에서 2026년 1순위 권장 알고리즘입니다.

Argon2 변형

변형특징권장
Argon2dGPU 공격 저항사이드채널 취약
Argon2i사이드채널 저항GPU 공격 취약
Argon2idd + i 혼합✅ 권장

Argon2 파라미터

Argon2id(memory, iterations, parallelism, password, salt)

- memory: 메모리 사용량 (KB)
- iterations: 반복 횟수
- parallelism: 병렬 스레드 수

OWASP 권장 설정 (2026)

최소 설정:
- memory: 64MB (65536 KB)
- iterations: 3
- parallelism: 4

높은 보안:
- memory: 256MB
- iterations: 4
- parallelism: 8

코드 예시

// Node.js with argon2
const argon2 = require('argon2');

// 해싱
const hash = await argon2.hash(password, {
  type: argon2.argon2id,
  memoryCost: 65536, // 64MB
  timeCost: 3,
  parallelism: 4
});

// 검증
const isValid = await argon2.verify(storedHash, inputPassword);
# Python with argon2-cffi
from argon2 import PasswordHasher

ph = PasswordHasher(
    memory_cost=65536,
    time_cost=3,
    parallelism=4
)

# 해싱
hash = ph.hash(password)

# 검증
try:
    ph.verify(stored_hash, input_password)
except VerifyMismatchError:
    # 비밀번호 불일치

bcrypt vs Argon2: 무엇을 선택할까?

비교표

항목bcryptArgon2id
나이1999년 (27년)2015년 (11년)
검증27년 실전 검증학술 검증 완료
메모리 조절
GPU 저항⚠️ 보통✅ 강함
라이브러리모든 언어 지원대부분 지원
OWASP 권장2순위1순위

선택 가이드

bcrypt 선택:

  • 레거시 시스템 호환 필요
  • 검증된 안정성 우선
  • 간단한 설정 선호

Argon2id 선택:

  • 새 프로젝트 시작
  • 최신 보안 표준 준수
  • 높은 GPU 저항 필요

2026 권장 순위 (OWASP)

1순위: Argon2id
2순위: bcrypt
3순위: scrypt
4순위: PBKDF2 (호환성 필요 시)

SHA-256을 사용해야 할 때

SHA-256은 비밀번호가 아닌 다른 용도에 완벽합니다.

적합한 용도

용도예시
파일 무결성다운로드 검증, 백업 확인
디지털 서명JWT, 인증서
블록체인비트코인 채굴
체크섬데이터 전송 검증
해시 테이블(HMAC과 함께) API 키 저장

코드 예시

// 파일 해시 (Node.js)
const crypto = require('crypto');
const fs = require('fs');

const fileBuffer = fs.readFileSync('file.zip');
const hash = crypto.createHash('sha256').update(fileBuffer).digest('hex');

console.log(hash); // "a1b2c3d4..."

실전 구현 체크리스트

비밀번호 저장

  • Argon2id 또는 bcrypt 사용
  • 적절한 work factor 설정 (250-500ms)
  • 라이브러리 자동 salt 생성 사용
  • 해시 결과 전체 저장 (salt 포함)

비밀번호 검증

  • 타이밍 공격 방지 비교 함수 사용
  • 검증 실패 시 일관된 응답 시간
  • 로그인 실패 횟수 제한

마이그레이션

  • 새 해시로 점진적 업그레이드
  • 로그인 성공 시 새 알고리즘으로 재해싱
  • 구 해시 식별 가능하도록 prefix 사용

FAQ

Q1: MD5로 저장된 기존 비밀번호는 어떻게 하나요?

A: 사용자가 로그인할 때 새 알고리즘으로 재해싱하세요.

// 로그인 성공 시
if (hash.startsWith('$md5$')) {
  // bcrypt로 재해싱
  const newHash = await bcrypt.hash(inputPassword, 12);
  await updateUserHash(userId, newHash);
}

Q2: bcrypt의 72바이트 제한은 문제 되지 않나요?

A: 대부분의 비밀번호는 72바이트 이내입니다. 더 긴 입력이 필요하면 먼저 SHA-256으로 해싱 후 bcrypt 적용하세요.

// 긴 비밀번호 처리
const prehash = crypto.createHash('sha256').update(password).digest('base64');
const finalHash = await bcrypt.hash(prehash, 12);

Q3: cost factor를 너무 높이면 DoS 공격에 취약하지 않나요?

A: 맞습니다. 로그인 요청 속도 제한(rate limiting)을 함께 구현하세요. 250-500ms가 적절한 균형점입니다.

Q4: pepper는 필요한가요?

A: pepper(애플리케이션 레벨 비밀 키)는 추가 보안을 제공하지만 필수는 아닙니다. salt만으로도 충분합니다.

Q5: 해시 온라인 도구를 사용해도 되나요?

A: 학습/테스트 목적으로만 사용하세요. 프로덕션에서는 서버 사이드에서 해싱해야 합니다. 해시 생성기는 100% 클라이언트에서 처리되어 안전합니다.


마무리

용도권장 알고리즘
비밀번호 저장Argon2id > bcrypt
파일 무결성SHA-256
디지털 서명SHA-256 / SHA-512
레거시 호환bcrypt / PBKDF2

핵심 원칙:

  1. 비밀번호에 빠른 해시(SHA-256, MD5) 절대 금지
  2. bcrypt cost 12 이상, Argon2 memory 64MB 이상
  3. 라이브러리 제공 salt 자동 생성 사용

관련 도구

도구용도
Hash GeneratorSHA-256, bcrypt 해시 생성
Password Generator강력한 비밀번호 생성
보안해싱SHA-256bcryptArgon2암호화개발

저자 소개

Toolypet Team

Toolypet Team

Development Team

The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.

Web DevelopmentCSS ToolsDeveloper ToolsSEOSecurity