Julia로 고급 비밀번호 관리자를 구축했습니다 (오, 그래, Juliaaaa)

발행: (2025년 11월 30일 오후 03:54 GMT+9)
6 min read
원문: Dev.to

Source: Dev.to

도구를 만들 때 같은 일을 두 번 반복하지 않으려고 하는데, 요즘은 아무도 기대하지 않는 언어로 만들고 있습니다. 이번에는 Julia 입니다. 모두가 수학과 머신러닝에 연관된 과학 언어라고 생각하죠. 혹시 반대 의견이 있으면 크게 외쳐 주세요.

왜 Julia이고 흔한 선택(Python/Go/Rust)이 아닌가?

  • 네이티브 성능: Julia는 LLVM을 통해 머신 코드로 컴파일됩니다. 키 파생, 반복 해싱 같은 암호학 연산이 많을 때 큰 차이가 납니다.
  • 표현력 있는 문법: 복잡한 수학(예: 엔트로피 계산)을 마치 수학처럼 적을 수 있습니다.
  • 다중 디스패치: 입력 타입에 따라 다른 동작을 정의할 수 있어 if/else로 뒤죽박죽 되는 코드를 피할 수 있습니다.
  • 대화형 REPL: 빠른 개발, 실시간 테스트, 즉석에서 조정이 가능합니다.
  • 놀라움: 아무도 기대하지 않기 때문에 재미있습니다.

아키텍처: “전문가 수준” 비밀번호 관리자는 무엇을 해야 할까?

보안 요구사항

  • 실제 암호화: AES‑256‑GCM을 시뮬레이션(데모에서는 XOR + 키 파생 사용, 구조는 Nettle.jl로 교체 가능)
  • 키 파생: 100,000 회 반복 PBKDF2(앞으로 Argon2로 교체 가능)
  • 고유 Salt: 암호화된 각 항목마다 암호학적으로 안전한 무작위 Salt 사용
  • Zero‑knowledge 아키텍처: 마스터 비밀번호는 절대 저장되지 않으며, 그로부터 키만 파생됨
  • 안전한 생성: Julia의 Random 모듈을 사용해 암호학적으로 안전한 난수원 활용

기능

  • 🎲 설정 가능한 옵션을 가진 비밀번호 생성기
  • 📊 엔트로피 계산기 (핵심 기능)
  • 💾 JSON 형식의 암호화 저장소
  • 🔍 비밀번호 비교 도구
  • 🎨 직관적인 CLI 인터페이스

엔트로피 모듈: 흥미로운 부분

엔트로피란?

암호학에서 엔트로피는 불확실성의 척도입니다. 즉, 비밀번호가 얼마나 예측 불가능한 비트 정보를 담고 있는지를 나타냅니다. 계산식은 다음과 같습니다.

H = L * log2(R)
  • L = 비밀번호 길이
  • R = 가능한 문자 “풀”의 크기

시각적 예시

전형적인 약한 비밀번호

Password123!
  • 길이: 12 문자
  • 감지된 풀: 소문자(26) + 대문자(26) + 숫자(10) + 기호(32) = 94 문자
  • 엔트로피: 12 × log₂(94) ≈ 78.5 비트
  • 추정 크래킹 시간: 약 95년(현대 GPU)

실제 문제: 사전 단어이며 예측 가능한 패턴을 따르므로 사전 공격으로 몇 분 안에 뚫립니다.

생성된 강력 비밀번호

xK9#mL2$pQ7@vR4!nF
  • 길이: 18 문자
  • 풀: 94 문자(전체 사용)
  • 엔트로피: 18 × log₂(94) ≈ 118 비트
  • 추정 크래킹 시간: ~1.05 × 10¹⁶ 년(실질적으로 무한)

Julia 구현

엔트로피 계산

function calculate_entropy(password::String)::Float64
    if isempty(password)
        return 0.0
    end

    # Detectar el pool de caracteres usado
    has_lowercase = any(c -> islowercase(c), password)
    has_uppercase = any(c -> isuppercase(c), password)
    has_digits    = any(c -> isdigit(c), password)
    has_special   = any(c -> !isalnum(c) && !isspace(c), password)

    # Calcular tamaño del pool
    pool_size = 0
    pool_size += has_lowercase ? 26 : 0
    pool_size += has_uppercase ? 26 : 0
    pool_size += has_digits    ? 10 : 0
    pool_size += has_special   ? 32 : 0

    # Fórmula de Shannon
    entropy = length(password) * log2(pool_size)
    return entropy
end

비밀번호 생성기

function generate_password(;
    length::Int=16,
    use_lowercase::Bool=true,
    use_uppercase::Bool=true,
    use_digits::Bool=true,
    use_special::Bool=true
)::String
    charset = Char[]
    use_lowercase && append!(charset, LOWERCASE)
    use_uppercase && append!(charset, UPPERCASE)
    use_digits    && append!(charset, DIGITS)
    use_special   && append!(charset, SPECIAL)

    # Generación criptográficamente segura
    password = String([rand(charset) for _ in 1:length])
    return password
end

키 파생 (PBKDF2)

function derive_key(master_password::String, salt::Vector{UInt8}, iterations::Int=100_000)::Vector{UInt8}
    # Aquí iría la llamada a una implementación de PBKDF2, por ejemplo usando
    # Crypto.jl o Nettle.jl. En el demo se muestra la estructura básica.
    # key = pbkdf2_hmac_sha256(master_password, salt, iterations, 32)
    # return key
end

(비밀번호 관리자의 나머지 코드, 암호화된 JSON 처리, CLI 및 테스트는 프로젝트 저장소에서 확인할 수 있습니다.)

Back to Blog

관련 글

더 보기 »

ECDSA 이해하기

이 글은 기본적으로 ECDSA Elliptic Curve Digital Signature Algorithm를 처음부터 이해하기 위한 연습입니다. 제가 가정하는 것은 기본적인 수학과 의지뿐입니다.