HANGUL.WIKI

bcrypt

bcrypt

번역 제공
2026-09-06
목차 (14개 섹션)

bcrypt는 1999년 Niels Provos와 David Mazières가 설계한 암호화 해시 함수로, 비밀번호 저장 및 검증에 특화된 적응형(adaptive) 해싱 알고리즘이다.

개요 및 배경

인터넷 서비스가 확산되면서 사용자 비밀번호를 안전하게 저장하는 것이 중요해졌다. 단순한 MD5나 SHA 계열 해시 함수는 비밀번호 저장에 적합하지 않다. 이 함수들은 연산 속도가 매우 빠르도록 설계되어 있어, 공격자가 GPU를 활용해 초당 수십억 개의 해시를 계산하는 무차별 대입 공격(Brute Force Attack)이나 사전 공격(Dictionary Attack)에 취약하기 때문이다.

bcrypt는 이 문제를 해결하기 위해 OpenBSD 프로젝트에서 Blowfish 블록 암호 알고리즘을 기반으로 설계되었다. 핵심 설계 목표는 의도적으로 연산 비용이 높은 해시 함수를 만드는 것으로, 공격자의 무차별 대입 공격을 현실적으로 불가능하게 만드는 데 있다.

핵심 특징

작업 인수(Work Factor/Cost Factor): bcrypt의 가장 중요한 특징은 연산 비용을 조절할 수 있는 작업 인수(일반적으로 4~31 범위)다. 이 값이 1 증가할 때마다 연산 시간이 2배씩 증가한다. 예를 들어 작업 인수가 12라면 2¹² = 4,096번의 키 확장 반복이 수행된다. 하드웨어 성능이 향상되더라도 작업 인수를 높여 보안 수준을 유지할 수 있어 '적응형(adaptive)' 해시 함수라 불린다.

솔트(Salt): bcrypt는 128비트(16바이트)의 무작위 솔트를 자동으로 생성하여 해시에 포함시킨다. 솔트는 동일한 비밀번호라도 서로 다른 해시값을 갖게 하여, 레인보우 테이블(Rainbow Table) 공격을 방어한다.

고정 길이 출력: bcrypt는 입력 길이와 관계없이 항상 60자의 해시 문자열을 출력한다.

해시 형식

bcrypt 해시는 다음 형식을 따른다.

`` $2b$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW `

각 부분의 의미는 다음과 같다.

  • $2b$: bcrypt 알고리즘 버전 식별자
  • 12: 작업 인수(cost factor)
  • 이후 22자: Base64 인코딩된 솔트
  • 마지막 31자: Base64 인코딩된 해시값

알고리즘 동작 원리

bcrypt는 Blowfish 암호의 키 스케줄링 알고리즘을 기반으로 한 EksBlowfishSetup` 함수를 핵심으로 한다. 비밀번호와 솔트를 사용하여 Blowfish의 키 확장(key setup)을 반복적으로 수행하고, 그 결과로 생성된 키 상태를 사용하여 고정된 텍스트("OrpheanBeholderScryDoubt")를 64번 암호화한 결과를 최종 해시로 사용한다.

한계 및 주의사항

최대 비밀번호 길이: 일부 bcrypt 구현체는 비밀번호를 72바이트로 제한한다. 72바이트를 초과하는 비밀번호는 잘려서 처리될 수 있으며, 이는 매우 긴 비밀번호의 보안성을 의도치 않게 낮출 수 있다.

Null 바이트 처리: C 언어 기반 구현체 중 일부는 Null 바이트에서 비밀번호를 잘라내는 취약점이 있을 수 있다.

현대적 대안

bcrypt 외에도 비밀번호 해싱에 적합한 알고리즘으로 scrypt(2009)와 Argon2(2015)가 있다. scrypt는 메모리 집약적 연산을 추가하여 GPU를 이용한 병렬 공격을 더욱 어렵게 하며, Argon2는 Password Hashing Competition(PHC)의 우승 알고리즘으로 메모리, CPU, 병렬성을 모두 조절할 수 있는 가장 현대적인 선택지다.

사용 현황

bcrypt는 Ruby on Rails, Laravel, Node.js(bcrypt 패키지), Python(passlib, bcrypt 라이브러리) 등 거의 모든 주요 웹 프레임워크와 언어에서 기본 또는 권장 비밀번호 해싱 방법으로 지원된다. 1999년에 설계된 알고리즘임에도 불구하고, 현재까지도 비밀번호 저장의 표준적인 선택으로 널리 사용되고 있다.

단계별 동작 절차

bcrypt는 사용자 비밀번호를 안전하게 저장하고 검증하기 위해 연산 단계를 순차적으로 실행하는 암호화 해시 함수다.

첫 번째 단계는 입력값 전달이다. 사용자가 설정한 비밀번호와 128비트(16바이트) 크기의 무작위 솔트가 알고리즘의 입력값으로 전달된다.

두 번째 단계는 반복적 키 확장(key setup) 수행이다. EksBlowfishSetup 함수는 입력된 비밀번호와 솔트를 사용하여 Blowfish 블록 암호의 키 상태를 확장한다. 키 확장은 작업 인수(cost factor)에 지정된 횟수만큼 반복 실행된다. 작업 인수가 12로 지정된 경우 2¹²에 해당하는 4,096번의 키 확장 반복이 진행된다.

세 번째 단계는 고정 텍스트 암호화 처리다. 키 확장을 통해 생성된 키 상태를 사용하여 "OrpheanBeholderScryDoubt"라는 고정된 텍스트를 64번 반복하여 암호화한다.

네 번째 단계는 최종 해시 문자열 생성이다. 알고리즘 버전 식별자, 작업 인수, Base64로 인코딩된 22자의 솔트, Base64로 인코딩된 31자의 최종 해시값이 결합되어 총 60자의 고정 길이 문자열로 출력된다.

보안 위협에 대한 대응 원리 및 조건

bcrypt는 웹 서비스 환경에서 사용자 비밀번호를 보호하기 위해 여러 보안 위협을 방어하도록 설계되었다.

무차별 대입 및 사전 공격 대응

bcrypt는 작업 인수를 통해 연산 비용을 의도적으로 높인다. 작업 인수가 1 증가할 때마다 연산 시간은 2배씩 늘어난다. 이 연산 지연은 공격자가 GPU를 활용하여 초당 수십억 개의 해시를 연산하는 무차별 대입 공격(Brute Force Attack)과 사전 공격(Dictionary Attack)의 진행을 어렵게 만드는 효과를 낸다. 하드웨어 연산 성능이 향상되는 환경에서는 작업 인수를 상향 조정해야 기존 보안 수준을 유지할 수 있는 조건이 따른다.

레인보우 테이블 공격 대응

bcrypt는 128비트(16바이트)의 무작위 솔트를 자동으로 생성하여 해시에 결합한다. 동일한 비밀번호가 입력되어도 솔트 값에 따라 서로 다른 60자의 해시 문자열이 생성된다. 이 구조는 미리 계산된 해시값을 사용하는 레인보우 테이블(Rainbow Table) 공격을 방어하는 효과를 낸다. 솔트 데이터는 최종 60자 해시 문자열 내에 22자 형태로 인코딩되어 포함되므로, 솔트 값 자체는 비밀로 유지되지 않는 것으로 보인다.

구현 환경에서의 기술적 제약

bcrypt는 특정 구현 환경과 입력 데이터에 따라 보안상의 제약과 예외가 존재한다.

첫째, 비밀번호 길이의 상한이다. 일부 bcrypt 구현체는 입력받는 비밀번호를 72바이트로 제한한다. 72바이트를 초과하는 비밀번호는 초과 부분이 잘려 처리될 수 있다. 이로 인해 72바이트를 초과하는 긴 비밀번호의 보안성이 의도치 않게 낮아질 수 있는 한계가 있다.

둘째, Null 바이트 처리에 따른 취약점이다. C 언어 기반의 일부 구현체에서는 Null 바이트가 포함되었을 때 비밀번호 입력을 잘라내는 취약점이 발생할 수 있는 것으로 알려졌다.

비밀번호 해시 알고리즘 비교

비밀번호 해시 함수는 무차별 대입 공격의 위협과 컴퓨터 연산 능력의 발전에 대응하며 발전해 왔다.

MD5 및 SHA 계열 해시 함수는 빠른 연산 속도를 목표로 설계되었다. 이 함수들은 연산 속도가 빨라 GPU를 활용한 대규모 해시 연산 공격에 취약하므로 비밀번호 저장에 적합하지 않다는 평가를 받는다.

bcrypt는 1999년 OpenBSD 프로젝트에서 Blowfish를 기반으로 설계되었다. bcrypt는 작업 인수를 통해 연산 시간을 조정하여 하드웨어 성능 향상에 대응하는 특성을 가진다.

scrypt는 2009년에 설계된 알고리즘이다. scrypt는 메모리 집약적 연산을 추가하여 GPU를 활용한 병렬 공격을 더욱 어렵게 만드는 효과를 제공한다.

Argon2는 2015년 Password Hashing Competition(PHC)에서 우승한 알고리즘이다. Argon2는 메모리, CPU, 병렬성을 모두 조절할 수 있는 기능을 갖추어 가장 현대적인 대안이라는 평가를 받는다.

프레임워크 및 라이브러리 지원 현황

bcrypt는 주요 웹 프레임워크와 프로그래밍 언어 환경에서 표준적인 비밀번호 저장 수단으로 활용된다.

웹 프레임워크 생태계에서는 Ruby on Rails와 Laravel 등 주요 프레임워크가 bcrypt를 기본 또는 권장 비밀번호 해싱 방법으로 지원한다.

프로그래밍 언어 생태계에서는 Node.js 환경의 bcrypt 패키지와 Python 환경의 passlib 및 bcrypt 라이브러리를 통해 기능이 제공된다.

bcrypt는 1999년에 설계된 알고리즘이나 현재까지도 비밀번호 저장을 위한 표준적인 선택으로 널리 사용되고 있는 것으로 알려졌다.

문서 정보

최초 작성
최종 갱신
분류
기술

HANGUL.WIKI가 정리·작성한 문서입니다. 정확성을 위해 노력하나 오류가 있을 수 있으므로, 중요한 내용은 공식 출처를 통해 확인하시기 바랍니다. 내용의 오류나 정정 요청은 오류·정정 신고로 알려주시면 검토 후 반영합니다.