흔한 탁상공론 보안 조회 대신, 파이썬과 K-익명성으로 구현하는 패스워드 유출 확인 엔진

흔한 탁상공론 보안 조회 대신, 파이썬과 K-익명성으로 구현하는 패스워드 유출 확인 엔진

안녕하세요. 현업에서 백엔드 및 자동화 프로그램을 개발하고 있는 개발자입니다.

최근 대규모 크리덴셜 스터핑(Credential Stuffing) 및 개인정보 유출 사고가 빈번하게 발생하면서, 내 계정의 안전 여부를 진단하는 토이 프로젝트나 서비스들이 많이 보입니다.

 

하지만 시중의 일부 초급 가이드나 대안들을 보면, 사용자가 입력한 비밀번호 원문이나 단순 해시값을 그대로 외부 API 서버에 HTTP 요청으로 쏘아 보내는 위험한 방식을 취하곤 합니다. 이는 전송 구간(In-Transit)에서 가로채기나 로그 유출이 발생할 수 있어 실제 프로덕션 환경에서는 절대 쓰이지 않는 '탁상공론형' 접근입니다.

이에 구글이나 글로벌 빅테크 기업들이 보안 조회에 표준적으로 사용하는 'K-익명성(K-Anonymity)' 아키텍처를 도입하여, 로컬 메모리 내부에서 안전하게 대조 작업을 처리하는 진단 엔진을 파이썬으로 구현해 보았습니다.

 

🛠 핵심 메커니즘: SHA-1 해시 슬라이싱 (Hash Slicing)

핵심은 사용자가 입력한 비밀번호의 SHA-1 해시값(40자리)을 온전하게 내보내지 않는 것입니다. 앞 5자리(Prefix)만 잘라서 외부 API 서버에 힌트로 던지면, 서버는 그 5자리로 시작하는 수만 개의 유출 서픽스(Suffix) 리스트를 덤프로 반환합니다. 진짜 대조 작업은 네트워크망이 아닌 내 컴퓨터의 로컬 메모리 안에서만 수행되므로 원천적으로 유출 가능성이 차단됩니다.

 

💻 핵심 구현 코드 (K-익명성 체크 로직)

import hashlib
import requests

def check_password_leak(password: str) -> int:
    # 1. SHA-1 해시 변환 및 대문자 처리
    sha1_hash = hashlib.sha1(password.encode("utf-8")).hexdigest().upper()

    # 2. K-익명성을 위한 해시 슬라이싱 (앞 5자리 Prefix, 뒤 35자리 Suffix)
    prefix = sha1_hash[:5]
    suffix = sha1_hash[5:]

    # 3. 앞 5자리 힌트만 외부 API 서버로 안전하게 전송
    url = f"https://api.pwnedpasswords.com/range/{prefix}"
    response = requests.get(url, timeout=5)

    if response.status_code != 200:
        raise RuntimeError("API 서버 연동에 실패했습니다.")

    # 4. 서버가 반환한 수만 개의 찌꺼기 명단(Suffix:Count)을 로컬 메모리에서 대조
    lines = response.text.splitlines()

    for line in lines:
        target_suffix, count = line.split(":")
        if target_suffix == suffix:
            return int(count)  # 일치하는 유출 횟수 반환

    return 0  # 유출 이력 없음

현업 표준인 pyproject.toml 구조로 의존성을 설계하고, 사용자가 브라우저에서 편리하게 조율할 수 있도록 Streamlit 대시보드 UI를 얹어 패키징했습니다.

전체 소스코드와 구체적인 UI 빌드 과정, 그리고 로컬 메모리 매칭 작업이 실제 어떤 무빙으로 안전하게 일치 판정을 내리는지 시각적으로 정리한 분석 내용은 아래 유튜브 콘텐츠를 참고해 주시면 감사하겠습니다.

 

👉유튜브 채널 '잡학다식 개발자' 영상 보기 : https://youtu.be/So49-1qf_ec

👉GitHub 오픈소스 저장소 : https://github.com/gohard-lab/pwned_credential_checker

 

댓글을 작성해보세요.

채널톡 아이콘