본문으로 건너뛰기
AZ Tools

scrypt 키 유도 (RFC 7914)

브라우저에서 scrypt로 비밀번호로부터 키를 유도하고, 메모리 비용과 PBKDF2·ROMix 중간 단계를 함께 보여 줍니다.

사용법

  1. RFC 7914 #1, #2, #3을 누르고 유도하면 RFC에 실린 키가 나옵니다. #1은 2단계에서 RFC의 ROMix 벡터도 재현합니다.
  2. 자신의 비밀번호와 솔트를 넣고(솔트가 원시 바이트면 16진수 체크) N, r, p, 키 길이를 고르세요.
  3. 유도하기 전에 메모리 수치를 보세요. 공격자에게는 추측 한 번의 비용이고, 서버에는 로그인 한 번의 비용입니다.
  4. 재현하려는 키를 기대하는 키 칸에 붙여넣으면 바이트 단위로 비교합니다.
  5. 새 비밀번호 저장에는 OWASP 프리셋에서 시작해, 유도 한 번이 감당할 수 있는 시간이 될 때까지 N을 올리세요.

자세한 설명

펼치기

비밀번호와 솔트로 scrypt를 실행하고, 비용 매개변수가 실제로 무엇을 사는지 확인합니다. scrypt는 세 단계입니다. 반복 1회의 PBKDF2-HMAC-SHA256이 비밀번호를 128 × r바이트 블록 p개로 늘리고, ROMix가 그런 블록 N개로 표를 채운 뒤 데이터에 따라 정해지는 순서로 다시 읽으며, 마지막으로 반복 1회의 PBKDF2가 섞인 블록을 솔트로 씁니다. 핵심은 이 표입니다. 한꺼번에 128 × r × N바이트가 필요하므로, PBKDF2나 bcrypt와 달리 공격자가 메모리 대신 코어를 늘리는 식으로 비용을 피할 수 없습니다. 매개변수를 바꾸면 그 크기를 바로 보여 줍니다. N = 2^14, r = 8이면 16 MiB이고, OWASP가 제시한 비밀번호 저장 최소값인 N = 2^17, r = 8, p = 1은 128 MiB입니다. 두 중간 단계도 출력합니다. RFC 7914의 첫 번째 벡터에서는 이 둘이 10절 ROMix 벡터의 입력과 출력 그대로이므로, 모든 단계를 믿는 대신 공개된 숫자와 비교할 수 있습니다. 매개변수 규칙은 RFC 그대로 지킵니다. 의외인 규칙도 하나 있습니다. N은 2^(16 × r)보다 작아야 해서 r = 1이면 최대 2^15이고, OpenSSL은 메모리에 넉넉히 들어가는데도 2^16을 거부합니다. 비밀번호는 UTF-8 바이트로 해시되므로, 눈에 같은 글자라도 유니코드 정규화 형식이 다르면(é를 한 코드포인트로 쓰느냐, e와 결합 악센트로 쓰느냐) 키가 달라집니다. 키 길이는 앞부분을 바꾸지 않습니다. 마지막 PBKDF2가 블록 단위로 출력을 만들기 때문에 32바이트 키는 같은 입력으로 만든 64바이트 키의 앞 절반입니다. 계산은 탭 안에서 하며 주기적으로 제어를 돌려주므로 큰 N도 진행률이 보이고 취소할 수 있습니다. RFC의 네 번째 벡터가 필요로 하는 1024 MiB까지 할당합니다.

자주 묻는 질문

N, r, p는 각각 무엇을 하나요?

N은 ROMix 표의 블록 수이자 섞는 횟수라서 메모리와 시간을 함께 정합니다. r은 각 블록의 크기(128바이트 단위)로, 올리면 메모리 접근 하나가 커지며 캐시 라인과 메모리 지연에 맞춰 보통 8을 씁니다. p는 서로 독립인 ROMix 계산의 개수로, 작업량을 곱하고 동시에 돌릴 때만 메모리도 곱합니다.

r = 1일 때 N이 왜 2^16이 될 수 없나요?

RFC 7914는 N이 2^(128 × r / 8)보다 작아야 한다고 정하며, r이 1이면 2^16입니다. 각 블록에서 뽑는 인덱스가 표 전체를 가리킬 만큼 크도록 하기 위한 규칙입니다. OpenSSL이 이를 지키고 이 페이지도 지키므로, 8 MiB면 충분히 들어가는데도 오류가 납니다. r = 2면 한도가 이미 2^32입니다.

다른 구현과 키가 왜 다르게 나오나요?

대개 들어가는 바이트가 다릅니다. 비밀번호가 UTF-8이고 같은 유니코드 정규화 형식인지, 솔트가 16진수나 base64 표기가 아니라 같은 바이트인지, N이 로그값이 아닌 값 자체인지 확인하세요. 어떤 라이브러리는 ln=14를, 어떤 것은 N=16384를 받습니다. 여기 1단계 값은 PBKDF2만의 결과이니, 그것부터 다르면 입력이 문제입니다.

짧은 키는 긴 키의 앞부분인가요?

그렇습니다. 마지막 단계인 PBKDF2가 요청 길이와 무관한 32바이트 블록 단위로 출력을 만들기 때문에, 64바이트 키의 앞 32바이트가 같은 입력의 32바이트 키입니다. 잘라 써도 안전하다는 뜻이지만, 같은 비밀번호에서 길이만 다르게 뽑은 두 키가 서로 독립적이지 않다는 뜻이기도 합니다.

실제 비밀번호 해시에 써도 되나요?

매개변수를 고르거나, 구현을 RFC와 대조하거나, 디버깅 중 저장된 해시를 재현하는 데 쓰세요. 비밀번호는 탭 밖으로 나가지 않지만 로컬 스토리지에 남고, 계산은 시간 측정 공격을 막도록 작성되지 않았습니다. 운영 환경에서는 플랫폼의 scrypt나 Argon2id를 사용자별 무작위 솔트와 함께 쓰고, 나중에 올릴 수 있도록 매개변수를 해시 옆에 저장하세요.

관련 도구