Bcrypt 해시 비밀번호를 데이터베이스에 저장하기 위해 어떤 열 유형 / 길이를 사용해야합니까?


317

BCrypt를 사용하여 해시 된 암호를 데이터베이스에 저장하고 싶습니다. 이것에 적합한 유형은 무엇이며 올바른 길이는 무엇입니까? BCrypt로 해시 된 비밀번호는 항상 같은 길이입니까?

편집하다

해시 예 :

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

일부 암호를 해시 한 후 BCrypt는 항상 60 자 해시를 생성하는 것으로 보입니다.

편집 2

구현을 언급하지 않아서 죄송합니다. jBCrypt 사용 하고 있습니다.


Openwall의 PHP 암호 해싱 프레임 워크 (PHPass) 도 참조하십시오 . 휴대 성이 뛰어나 사용자 암호에 대한 여러 가지 일반적인 공격에 대비하여 강화되었습니다. 프레임 워크를 작성한 사람 (SolarDesigner)은 John The Ripper 를 쓴 사람과 동일 하며 Password Hashing Competition 의 심사 위원으로 활동합니다 . 그래서 그는 암호 공격에 대해 알고 있습니다.
jww

1
누군가가 이것에 대해 scrypt 솔루션을 찾고 있다면 : Gumbo의 대답은 scrypt에도 적용됩니다. 개인적으로 MySQL에서 BINARY (64)를 적용했으며 나중에 파이썬에서 바이트 동등성을 테스트 할 수있었습니다.
Philippe Hebert

답변:


368

bcrypt의 모듈 식 암호화 형식은

  • $2$, $2a$또는 $2y$식별 해시 알고리즘 및 형식
  • 비용 매개 변수를 나타내는 두 자리 숫자 값 $
  • 53 문자 길이 값베이스 64 인코딩 (그들은 문자를 사용하여 ., /, 0- 9, A- Z, a- z받는 다르다고 표준베이스 64 인코딩 알파벳)로 이루어진 :
    • 22 문자의 소금 (실제로 128 비트의 132 디코딩 비트)
    • 31 자의 암호화 된 출력 (186 개의 디코딩 된 비트 중 184 비트 만 유효)

따라서 총 길이는 각각 59 또는 60 바이트입니다.

2a 형식을 사용하면 60 바이트가 필요합니다. 따라서 MySQL을 위해 나는를 사용하는 것이 좋습니다 것 CHAR(60) BINARY또는BINARY(60) (참조 _bin바이너리 데이터 정렬 의 차이에 대한 정보를).

CHAR이진 안전이 아니며 동등성은 바이트 값에만 의존하는 것이 아니라 실제 데이터 정렬에 의존합니다. 최악의 경우 A는로 취급됩니다 a. 자세한 내용 _binbinary데이터 정렬 을 참조하십시오.


28
바이너리 (60)로 저장하면 문자열 등가에 예기치 않은 동작이 발생할 수 있습니다. .NET에서는 String.Equals (fromDataBaseBinary60string, typicalishString, StringComparison.InvariantCulture)를 사용하여 극복 할 수 있습니다.
JHubbard80

8
열을 CHAR (60) CHARACTER SET latin1 COLLATE latin1_bin으로 정의하면 이진 열이 없어도 정확한 문자열 비교의 이점을 얻을 수 있습니다.
Ben

2
@AndreFigueiredo SQL_Latin1_General_CP1_CS_AS는 MySQL에서 알려져 있지 않습니다. 알려진 것은 latin1_general_cs입니다.
Gumbo

1
여기에 대한 정의를 가지고 싶지만 무엇을 2, 2a2y해시 알고리즘 및 형식에 대한 의미한다. 몇 가지 검색으로 쉬운 답변을 찾지 못했습니다.
jocull

2
@Neon 문제는 다른 해시를 동일하게 비교할 수 있다는 것입니다. 이진 열 (또는 올바른 데이터 정렬이있는 VARCHAR)임을 명시 적으로 지정하면 다른 설정을 변경하여 대소 문자를 구분하지 않는 위험이 발생하지 않습니다. 또한 의도를 더 명확하게 만듭니다. 일반적으로 이진 데이터를 저장하는 것이 좋습니다. 이진 데이터로 저장해야합니다.
모니카 펀드의 소송

51

Bcrypt 해시는 BINARY(40)열에 저장 될 수 있습니다 .

BINARY(60)다른 답변에서 알 수 있듯이 가장 쉽고 자연스러운 선택이지만 스토리지 효율성을 극대화하려면 해시를 무손실로 해체하여 20 바이트를 절약 할 수 있습니다. 나는 이것을 GitHub에 더 철저하게 문서화했다 : https://github.com/ademarre/binary-mcf

Bcrypt 해시는 모듈 식 암호화 형식 (MCF)이라고하는 구조를 따릅니다. 이진 MCF (BMCF)는 이러한 텍스트 해시 표현을보다 간결한 이진 구조로 디코딩합니다. Bcrypt의 경우 결과 이진 해시는 40 바이트입니다.

Gumbo는 Bcrypt MCF 해시의 4 가지 구성 요소를 잘 설명했습니다.

$<id>$<cost>$<salt><digest>

BMCF 로의 디코딩은 다음과 같습니다.

  1. $<id>$ 3 비트로 표현 될 수있다.
  2. <cost>$, 04-31은 5 비트로 표시 될 수 있습니다. 이것들을 1 바이트로 합치십시오.
  3. 22 자의 솔트는 128 비트의 비표준 base-64 표현입니다. Base-64 디코딩은 16 바이트를 생성합니다.
  4. 31 자 해시 다이제스트는 base-64를 23 바이트로 디코딩 할 수 있습니다.
  5. 40 바이트를 모두 합치십시오. 1 + 16 + 23

위의 링크에서 자세한 내용을 읽거나 GitHub에서 PHP 구현을 검사 할 수 있습니다.


49
더 긴 필드 비용 : 20 바이트 곱하기 백만 + 레코드 : 백만 레코드에 도달하면 20MB + 매우 복잡한 보안 및 엔지니어링 분야에서 단축 된 필드 길이를 잘못 구현하는 비용 : $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$ 당신은 수학을합니다.
Kzqai

6
@Kzqai는 앞서 언급했듯이 60 바이트 큰 열이 가장 자연스러운 선택이지만 스토리지 효율성을 추구하는 것이 프로젝트에 따라 얼마나 많은 영향을 미치는지에 대해 설명합니다. 예를 들어, 전체 데이터베이스를 메모리에 맞추려고 시도하는 것이 일반적이며 여기서 20MB는 메모리 제한 환경에서 빠르게 추가 할 수 있습니다.
Andre D

10
당신의 예는 내 요점에 들어갑니다. --- 데이터베이스를 메모리에 저장하려면 bcrypt 스토리지 열을 터치하기 전에 다른 모든 열을 최적화하십시오. --- 다른 모든 열을 제 정도로 최적화하고 bcrypt 해시 열만 남은 경우 bcrypt에 대해서만 다른 메모리를 가져옵니다. --- 위의 두 가지를 모두 수행 한 경우 ... ... 중지, 낮은 매달린 과일의 다른 모든 열을 최적화하지 않았으며 작동하는 테스트 된 암호화 보안 시스템을 엉망으로 만들려고합니다. 구현에 실패 할 가능성이있는보다 복잡한 자체 개발 시스템을 사용합니다.
Kzqai

11
@Kzqai Bcrypt 라이브러리의 보안을 약화시킬 위험은 없습니다. 암호 확인 전에 저장소에서 검색 할 때 실행 취소되는 데이터 인코딩입니다. 이것은 "자신의 암호를 굴리지 마십시오"영역이 아닙니다.
Andre D

1
좋은 설명입니다. :) 당신의 설명이 좋은 아이디어를 주었지만, 나는 단지 안전한면에 있기 위해 60 문자, 심지어 100 문자로 가고 싶습니다. @Kzqai와 AndreD
Naveen Kumar V

23

bcrypt 해시를 생성하기 password_hash()위해 PASSWORD_DEFAULT알고리즘 과 함께 PHP를 사용하는 경우 (이 질문을 읽는 사람들의 대다수라고 가정 할 것입니다.) 앞으로 password_hash()다른 알고리즘을 기본값으로 사용할 수 있으므로이를 염두에 두십시오. 해시의 길이에 영향을 미칩니다 (그러나 반드시 더 길지는 않을 수도 있습니다).

매뉴얼 페이지에서 :

이 상수는 새롭고 강력한 알고리즘이 PHP에 추가됨에 따라 시간이 지남에 따라 변경되도록 설계되었습니다. 따라서이 식별자를 사용한 결과의 길이는 시간이 지남에 따라 변경 될 수 있습니다. 따라서 결과를 60 자 이상으로 확장 할 수있는 데이터베이스 열에 저장하는 것이 좋습니다 (255 자 선택이 좋습니다).

255 바이트 암호 해시를 저장하는 10 억 명의 사용자 (즉, 현재 페이스 북과 경쟁하고 있음)가 있더라도 bcrypt를 사용하면 작은 SSD 하드 드라이브 크기와 비슷한 ~ 255GB의 데이터 만 남게됩니다. 암호 해시 저장이 응용 프로그램의 병목 현상이 될 가능성은 거의 없습니다. 그러나 스토리지 공간이 어떤 이유로 든 실제로 문제 될 가능성이 있지만 기본값이 아닌 경우에도 bcrypt PASSWORD_BCRYPT를 강제 password_hash()로 사용하는 데 사용할 수 있습니다 . 새로운 PHP 버전이 출시 될 때마다 bcrypt에서 발견 된 취약점에 대한 정보를 유지하고 릴리스 정보를 검토하십시오. 기본 알고리즘이 변경된 경우 이유 를 검토 하고 새 알고리즘의 사용 여부에 대한 정보를 바탕으로 결정을 내리는 것이 좋습니다.


20

MD5 해시와 같이이를 저장할 수있는 깔끔한 트릭이 있다고 생각하지 않습니다.

가장 좋은 방법 CHAR(60)은 항상 60 자 이므로 그대로 저장하는 것입니다.


PHP 문서에 따르면 향후 릴리스를 위해 열이 더 많은 데이터를 보유 할 수 있어야합니다.
Julian F. Weinert

16
금판에 이유가 없습니다. 사용중인 소프트웨어에 60 바이트가 필요한 경우 60 바이트를 할당하십시오. 소프트웨어를 변경하여 향후에 릴리스 할 예정인 경우 해당 릴리스가 발생할 때 걱정할 수 있습니다. 기능 변경 업데이트를 자동으로 설치해서는 안됩니다.
Tyler Crompton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.