해시 된 비밀번호 필드에 사용할 데이터 유형 및 길이는 무엇입니까?


268

암호 해싱의 작동 방식을 잘 모르겠지만 (나중에 구현할 예정 임) 지금 데이터베이스 스키마를 만들어야합니다.

암호를 4-20 자로 제한하려고 생각하지만 해시 문자열을 암호화 한 후 이해하면 길이가 다릅니다.

그렇다면 데이터베이스에 이러한 암호를 저장하는 방법은 무엇입니까?


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

2
비밀번호에 상한을 두지 마십시오. 해시하고 있으며 상한에 대한 저장 이유가 없습니다. 암호 해시를 사용한 DoS 공격이 걱정된다면 1000 또는 1024가 적절한 상한입니다.
Iiridayn

왜 비밀번호 길이를 제한합니까? 적어도 사용자가 100 자로 된 비밀번호를 만들도록 허용 :)
Andrew

비밀번호는 사소한 암호이므로 4 문자는 매우 위험한 하한입니다. 최소한 8을 사용하지만 14 또는 16이 훨씬 좋습니다.
quikchange

이것은 답변이 오래된 매우 오래된 질문입니다. 최신 Gilles 답변 을 참조하십시오 .
kelalaka

답변:


448

업데이트 : 단순히 해시 기능을 사용하는 것이 암호를 저장하기에 충분하지 않습니다. 자세한 설명 은이 스레드에서 Gilles의 답변을 읽어야 합니다 .

암호의 경우 Bcrypt 또는 Argon2i와 같은 키 강화 해시 알고리즘을 사용하십시오. 예를 들어, PHP에서는 기본적으로 Bcrypt를 사용하는 password_hash () 함수 를 사용하십시오.

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

결과는 다음과 유사한 60 자 문자열입니다 (단, 고유 한 소금을 생성하기 때문에 숫자가 다름).

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

SQL 데이터 유형 CHAR(60)을 사용하여이 Bcrypt 해시 인코딩을 저장하십시오. 이 함수는 16 진수 문자열로 인코딩되지 않으므로 이진수로 저장하기 위해 쉽게 16 진수를 풀 수 없습니다.

다른 해시 함수는 여전히 사용하지만 암호 저장에는 사용하지 않으므로 2008 년에 작성된 원래 답변을 아래에 유지합니다.


사용하는 해시 알고리즘에 따라 다릅니다. 해싱은 입력에 관계없이 항상 같은 길이의 결과를 생성합니다. 이진 해시 결과를 일련의 16 진수로 텍스트로 나타내는 것이 일반적입니다. 또는이 UNHEX()함수를 사용하여 16 진수 문자열을 반으로 줄일 수 있습니다 .

  • MD5는 128 비트 해시 값을 생성합니다. CHAR (32) 또는 BINARY (16)을 사용할 수 있습니다
  • SHA-1은 160 비트 해시 값을 생성합니다. CHAR (40) 또는 BINARY (20)를 사용할 수 있습니다
  • SHA-224는 224 비트 해시 값을 생성합니다. CHAR (56) 또는 BINARY (28)를 사용할 수 있습니다
  • SHA-256은 256 비트 해시 값을 생성합니다. CHAR (64) 또는 BINARY (32)를 사용할 수 있습니다
  • SHA-384는 384 비트 해시 값을 생성합니다. CHAR (96) 또는 BINARY (48)를 사용할 수 있습니다
  • SHA-512는 512 비트 해시 값을 생성합니다. CHAR (128) 또는 BINARY (64)를 사용할 수 있습니다
  • BCrypt는 구현에 따른 448 비트 해시 값을 생성합니다. CHAR (56), CHAR (60), CHAR (76), BINARY (56) 또는 BINARY (60)가 필요할 수 있습니다.

2015 년 현재 NIST 상호 운용성을 필요로하는 해시 함수 응용 프로그램에 SHA-256 이상사용할 것을 권장 합니다. 그러나 NIST는 암호를 안전하게 저장하기 위해 이러한 간단한 해시 함수를 사용하지 않는 것이 좋습니다.

적은 해싱 알고리즘은 상호 교환이 아닌 응용 프로그램 내부와 같은 용도로 사용되지만 크랙킹 가능한 것으로 알려져 있습니다 .


47
@Hippo : 사용자 이름을 소금으로 사용하지 마십시오. 사용자 당 임의의 소금을 생성하십시오.
Bill Karwin

11
예, 같은 행에 저장하지 않을 이유가 없습니다. 공격자가 데이터베이스에 액세스하더라도 해당 소금을 기반으로 레인보우 테이블을 구성해야합니다. 그리고 그것은 단순히 암호를 추측하는 것만 큼 많은 일입니다.
Bill Karwin

5
@ SgtPooki : 소금을 평문으로 저장하려면 다른 열이 필요합니다. 그런 다음 사용자가 입력 할 때 동일한 소금으로 사용자의 비밀번호를 해시하고 결과를 테이블에 저장된 해시 다이제스트와 비교할 수 있습니다.
Bill Karwin

12
동일한 테이블 (또는 동일한 액세스 권한이있는 다른 위치)에 솔트를 저장하는 경우 사용자마다 고유하므로 사용자 이름을 솔트로 사용하지 않는 이유는 없습니다. 그러나 알려진 모든 소금은 알려진 소금이없는 경우보다 해시를 암호화 적으로 약하게 만듭니다. 소금도 알 수없는 경우에만 가치를 더합니다.
fijiaaron

9
알려진 소금과 알려지지 않은 소금의 거래를 이해하지 못합니다. 사이트를 구현하는 경우 비밀번호를 테스트하는 로그인 페이지 / 스크립트 / 서비스에 소금을 알고 있어야합니다. 그래서 당신은 "알 수없는"소금 옹호자입니다 – 당신은 로그인 프로세스를위한 코드가 공격자에게 알려지지 않았다고 가정하고 있습니까? 그렇지 않다면, 공격자 는 소금이 무작위이거나 고유하거나 해시 된 암호와 함께 저장되거나 따로 저장되어 있는지 항상 알지 못 합니까?
mattstuehler

13

각 해싱 알고리즘은 항상 같은 수의 문자로 평가되므로 실제로 CHAR(해시 길이) 를 사용하여 MySQL의 데이터 유형을 정의 할 수 있습니다. 예를 들어, SHA1항상 40 자 16 진수를 반환합니다.


1
SHA-1은 암호 해싱에 적합하지 않습니다.
Gilles 'SO- 악한 중지'

10

항상 암호 해싱 알고리즘 Argon2 , scrypt , bcrypt 또는 PBKDF2를 사용하십시오 .

Argon2 는 2015 비밀번호 해싱 대회에서 우승했습니다. Scrypt , bcryptPBKDF2 는 현재 덜 선호되는 것으로 여겨지지만 여전히 근본적으로 건전한 오래된 알고리즘이므로 아직 플랫폼에서 Argon2를 지원하지 않는 경우 다른 알고리즘을 사용하는 것이 좋습니다.

데이터베이스에 직접 비밀번호를 저장하지 마십시오. 암호화하지 마십시오. 그렇지 않으면 사이트가 손상되면 공격자가 암호 해독 키를 얻어 모든 암호를 얻을 수 있습니다. 비밀번호는 반드시 해시 되어야 합니다 .

암호 해시는 해시 테이블 해시 또는 암호화 해시는 다른 특성을 가지고있다. 암호에 MD5, SHA-256 또는 SHA-512와 같은 일반 암호화 해시를 사용하지 마십시오. 비밀번호 해싱 알고리즘 은 고유 한 salt를 사용합니다 (다른 사용자 또는 다른 사람의 데이터베이스에서는 사용되지 않음). 솔트는 공격자가 공통 암호의 해시를 미리 계산할 수 없도록하는 데 필요합니다. 솔트를 사용하면 모든 계정에 대해 계산을 다시 시작해야합니다. 암호 해싱 알고리즘은 본질적으로 속도느립니다 . 공격자는 여러 가지 암호를 시도해야하기 때문에 속도가 느려져 공격자에게 많은 피해를줍니다. 자세한 내용은 비밀번호를 안전하게 해시하는 방법을 참조하십시오 .

비밀번호 해시는 4 가지 정보를 인코딩합니다.

  • 사용되는 알고리즘의 표시기. 민첩성에 필요합니다 . 암호화 권장 사항은 시간이 지남에 따라 변경됩니다. 새로운 알고리즘으로 전환 할 수 있어야합니다.
  • 난이도 또는 경도 표시기. 이 값이 클수록 해시를 계산하는 데 더 많은 계산이 필요합니다. 이것은 암호 변경 기능에서 일정하거나 전역적인 구성 값이어야하지만 컴퓨터가 빨라질수록 시간이 지남에 따라 증가해야하므로 각 계정의 값을 기억해야합니다. 일부 알고리즘에는 단일 숫자 값이 있고 다른 알고리즘에는 더 많은 매개 변수가 있습니다 (예 : CPU 사용 및 RAM 사용을 개별적으로 조정).
  • 소금. 솔트는 전체적으로 고유해야하기 때문에 각 계정마다 저장해야합니다. 소금은 암호를 변경할 때마다 무작위로 생성되어야합니다.
  • 해시 특성, 즉 해싱 알고리즘의 수학적 계산 결과.

많은 라이브러리에는이 정보를 단일 문자열로 편리하게 패키징하는 페어 함수가 포함되어 있습니다. 하나는 알고리즘 표시기, 경도 표시기 및 암호를 사용하고 임의의 솔트를 생성하고 전체 해시 문자열을 반환합니다. 암호와 전체 해시 문자열을 입력으로 사용하고 암호가 올바른지 여부를 나타내는 부울을 반환합니다. 보편적 인 표준은 없지만 일반적인 인코딩은

$ 알고리즘 $ 매개 변수 $ salt $ 출력

여기서 algorithm숫자 또는 알고리즘의 선택을 인코딩하는 짧은 영숫자 문자열 인 parameters인쇄용 문자열이며, salt그리고 output종료하지 않고있는 Base64 인코딩된다 =.

16 바이트이면 소금과 출력에 충분합니다. (예를 들어 Argon2 권장 사항 참조 ) Base64로 인코딩되며 각각 21 자입니다. 다른 두 부분은 알고리즘과 매개 변수에 따라 다르지만 일반적으로 20-40 자입니다. 총 약 82 개의 ASCII 문자 ( CHAR(82)유니 코드가 필요 없음)이며 나중에 필드를 확장하기가 어렵다고 생각되면 안전 마진을 추가해야합니다.

해시를 이진 형식으로 인코딩하면 알고리즘의 경우 1 바이트, 경도의 경우 1-4 바이트 (파라미터 중 일부를 하드 코딩 한 경우), 소금 및 출력의 경우 각각 16 바이트로 줄일 수 있습니다. 총 37 바이트입니다. 최소 2 바이트의 스페어 바이트를 갖도록 40 바이트 ( BINARY(40)) 라고 말하십시오 . 이들은 인쇄 가능한 문자가 아닌 8 비트 바이트이며 특히 필드에 널 바이트가 포함될 수 있습니다.

해시의 길이는 암호의 길이와 완전히 관련이 없습니다.


9

이 위키피디아 기사는 소금에 절이는 가치가 있습니다. 아이디어는 해시 값을 무작위 화하기 위해 데이터 세트를 추가하는 것입니다. 이렇게하면 누군가 비밀번호 해시에 무단 액세스 할 경우 사전 공격으로부터 비밀번호를 보호 할 수 있습니다.


2
그것은 실제로 매우 가치가 있지만 (+1), 그것은 질문에 대답하지 않습니다! (-1)
Bill Karwin

3
그렇습니다. 그러나이 맥락에서 확실히 관련이 있습니다 (+1)
Treb

7

고정 길이 문자열 (VARCHAR (n) 또는 MySQL이 호출) 해시는 항상 고정 길이 (예 : 사용하는 해시 알고리즘에 따라 12 자)입니다. 따라서 20 자 암호는 12 자 해시로 줄어들고 4 자 암호는 12 자 해시도 생성합니다.


3
또는 MySQL은 그것을 호출합니다-MYSQL은 그것을 CHAR이라고 부릅니다. 이 유형은 고정 길이 값입니다. 그래서 나는 CHAR이 VARCHAR보다 더 나은 유형이라고 생각합니다.
t298712383

4

TEXT순방향 호환성을 위해 (무한한 수의 문자 저장)을 사용해야합니다 . 해싱 알고리즘 (필요한)은 시간이 지남에 따라 더 강력 해 지므로이 데이터베이스 필드는 시간이 지남에 따라 더 많은 문자를 지원해야합니다. 또한 마이그레이션 전략에 따라 동일한 필드에 새 해시와 기존 해시를 저장해야 할 수도 있으므로 길이를 한 가지 유형의 해시로 고정하지 않는 것이 좋습니다.


3

실제로 사용중인 해싱 알고리즘에 따라 다릅니다. 암호의 길이는 올바르게 기억한다면 해시의 길이와 거의 관련이 없습니다. 사용중인 해싱 알고리즘의 사양을 확인하고 몇 가지 테스트를 실행 한 다음 바로 그 위를 자릅니다.


3

해시는 일련의 비트 (알고리즘에 따라 128 비트, 160 비트, 256 비트 등)입니다. MySQL에서 허용하는 경우 열은 텍스트 / 문자 유형이 아닌 이진 유형이어야합니다 (SQL Server 데이터 유형은 binary(n)또는 varbinary(n)). 해시에도 소금을 바르십시오. 소금은 텍스트 또는 이진일 수 있으며 해당 열이 필요합니다.


정의는 여기에서 완전히 정확합니다-MySQL 은이 값을 숫자 값으로 저장하고 문자열 일치를 수행하는 것 보다이 열에서 훨씬 효율적으로 검색 할 수 있지만 소금은 소금에 절인 데이터 옆에 데이터베이스에 저장해서는 안됩니다-소금이 제공하는 안전성을 제거합니다 .
Tony Maro

6
소금은 비밀 이 아닙니다 . 에만 비밀 암호입니다. 모든 새 비밀번호에 새 소금이 있는지 확인하십시오. 사용자가 비밀번호를 변경할 때마다 시스템은 해당 비밀번호에 대한 새 솔트를 생성해야합니다. 솔트는 암호로 안전한 PRNG에서 생성 된 16 바이트와 같이 길고 무작위이어야합니다.
yfeldblum

1
@TonyMaro SQL 수준에서 일치하는 암호 문자열이 좋은 전략인지 확실하지 않습니다. 즉, 데이터베이스에서 비밀번호를 검색하지 말고 대신 사용자 이름을 기준으로 사용자를 검색하고 SQL이 아닌 코드에서 비밀번호를 비교해야합니다.
bart

1

나는 항상 암호화 된 문자열의 MAX 문자열 길이를 찾아 VARCHAR 유형의 문자 길이로 설정하도록 테스트했습니다. 보유 할 레코드 수에 따라 실제로 데이터베이스 크기에 도움이 될 수 있습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.