Python

[Python] 해시(Hash) 알고리즘 : 안전한 비밀번호 암호화 구현하기

dev-grace 2024. 12. 23. 21:53

이번 포스트에서는 사용자 비밀번호를 안전하게 보호하기 위한 해시 알고리즘 구현 방법과 고려사항에 대해 다룰 예정이다.

1. 비밀번호 암호화의 필요성

현대 웹 서비스에서 사용자 비밀번호를 안전하게 보호하는 것은 필수이다. 암호화되지 않은 비밀번호는 다음과 같은 보안 위험을 초래할 수 있다.

1-1. 보안 위험

  • 데이터베이스 유출 사고 발생 가능성
  • 평문 저장 시 즉시 노출 위험
  • 해킹으로 인한 사용자 정보 유출 위험

 

이러한 위험을 방지하기 위해 해시(Hash) 알고리즘을 사용한 암호화가 필요하다. 해시의 주요 장점은 다음과 같다.

1-2. 해싱의 장점

  • 단방향 암호화로 원본 복원 불가
  • 동일 입력값에 대한 일관된 해시값 생성
  • 데이터베이스 저장 시 추가적인 보안층 제공

 

2. 암호화 구현 방법

2-1. bcrypt를 활용한 방법

import bcrypt

# 비밀번호 해싱
password = b"myPassword123"
hashed = bcrypt.hashpw(password, bcrypt.gensalt())

# 비밀번호 검증
def verify_password(plain_password, hashed_password):
	return bcrypt.checkpw(plain_password, hashed_password)

 

2-2. hashlib을 활용한 고급 해싱

import hashlib
import binascii

def hash_password(password):
	# 솔트 생성 및 해싱
    salt = b"unique_salt_per_user" # 실제 구현시 사용자별 고유값 사용
    key = hashlib.pbkdf2_hmac(
    	'sha512',
        password.encode('utf-8'),
        salt,
        100000 # 반복 횟수
    )
    return binascii.hexlify(key)
    
print(hashlib.algorithms_available)
# {'blake2b', 'blake2s', 'md5', 'md5-sha1', 'ripemd160', 'sha1', 'sha224', 'sha256', 'sha384', 'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', 'sha512', 'sha512_224', 'sha512_256', 'shake_128', 'shake_256', 'sm3'}

 

 

3. 구현 시 고려사항

3-1. 보안 고려사항

  • 솔트(Salt) 값을 사용자별로 유니크하게 생성
  • 충분한 해싱 반복 횟수 설정 (최소 100,000회 이상 권장)
  • 안전한 해시 알고리즘 선택 (SHA-512, bcrypt 등)

3-2. 성능 고려사항

  • 적절한 반복 횟수 설정으로 보안과 성능 밸런스 유지
  • 해싱 작업은 CPU 자원을 많이 사용하므로 비동기 처리 고려

 

4. 실제 구현 예시

class UserAuth:
    def __init__(self):
        self.salt_rounds = 12  # bcrypt 보안 수준
    
    def hash_password(self, plain_password):
        return bcrypt.hashpw(plain_password.encode('utf-8'), bcrypt.gensalt(self.salt_rounds))
    
    def verify_password(self, plain_password, hashed_password):
        return bcrypt.checkpw(plain_password.encode('utf-8'), hashed_password)
    
    def register_user(self, username, password):
        hashed_password = self.hash_password(password)
        # DB 저장 로직
        return {"username": username, "password": hashed_password}
 

+) bcrypt의 salt_rounds는 해시를 생성할 때 수행되는 내부 반복 횟수를 결정하는 값이다.

이 값이 1 증가할 때마다 해싱 작업량이 2배로 증가한다.

 

예시)

  • `rounds = 10`: 2¹⁰ = 1,024번 반복
  • `rounds = 11`: 2¹¹ = 2,048번 반복
  • `rounds = 12`: 2¹² = 4,096번 반복
  • `rounds = 13`: 2¹³ = 8,192번 반복

따라서 salt_rounds 값이 높아질수록,

  • 장점
    • 보안 수준이 높아진다.
    • 해시를 크래킹하는데 더 많은 시간과 컴퓨팅 자원이 필요하다.
    • 무차별 대입 공격(Brute Force)에 대한 저항성이 증가한다.
  • 단점
    • 해시를 생성하는 시간이 기하급수적으로 증가한다.
    • 서버의 CPU 사용량이 증가한다.
    • 사용자 인증 시 대기 시간이 길어진다.
  • 일반적으로 권장되는 값
    • 최소 10 이상을 권장
    • 서버 성능에 따라 10-14 사이의 값을 선택