Menu
CoddyTech

비밀번호를 저장하지 않기

Coddy Node.js 여정의 인증과 보안 섹션에 포함된 레슨. 24개 중 4번째.

사람들은 비밀번호를 재사용하므로, 유출된 평문 비밀번호로 다른 곳의 계정도 노출될 수 있습니다. 솔트가 적용된 비밀번호 해시를 저장하세요. 이는 디코딩하는 대신 다시 계산하여 검증하는 파생 값입니다.

const salt = randomBytes(16).toString('hex');
const key = await scryptAsync(inviteCode, salt, 32);
const saved = salt + '.' + key.toString('hex');

이 예제에서는 초대 코드에 솔트와 파생 키를 결합합니다. 구분 기호를 사용하면 검증할 때 솔트를 복구하고 동일한 매개변수로 다른 키를 파생할 수 있습니다. 비밀번호 과제에서는 자체 구분 기호와 키 길이를 사용합니다. 새 비밀번호마다 솔트를 생성하고, 키를 파생한 다음 둘 다 저장하세요. 공격자는 추측을 시도할 수 있으므로 솔트가 적용된 해시를 사용하더라도 강력한 비밀번호가 필요합니다.

challenge icon

챌린지

쉬움

현재 가입에서는 각 비밀번호를 입력한 그대로 저장합니다. 데이터베이스가 유출되어도 비밀번호가 노출되지 않도록, 대신 솔트를 사용한 해시를 저장하게 만드세요.

  1. passwords.js에서 hashPassword(password)를 변경하여 가입 시 저장할 문자열을 솔트, 콜론, 해시 순서로 반환하게 하세요.
    • 솔트는 무작위 바이트 16개이며, 호출할 때마다 새로 생성하고 16진수로 기록합니다. 즉, 0부터 9까지와 a부터 f까지의 문자 32개입니다.
    • 해시는 scrypt가 비밀번호와 해당 솔트로 만드는 64바이트 키이며, 이것도 16진수로 기록합니다. 즉, 문자 128개입니다. scryptAsync의 세 번째 인수는 바이트 단위의 키 길이입니다.
    • 두 값 사이에 콜론을 넣으세요. 저장된 값은 다음과 같은 형태입니다. f2bba0669d9fa2d203afc7e61bf8f065:c3f7cae352e023a8d4766da9a316b5a2c844100efff22c4079f89a8ab8512ac91c33227481c3afa88c3ba0e88347f9e3e0c22dad9d55f19688a350f71be8dbd2
  2. server.js는 변경할 필요가 없습니다. 그 안의 POST /signup은 이미 hashPassword를 호출하고 반환된 값을 저장합니다. 또한 사용자 한 명에 대해 저장된 값을 보여 주는 GET /debug/users/:username도 있습니다. 이 경로는 확인할 수 있도록 마련된 것일 뿐이며, 실제 앱에는 절대 없습니다.

직접 해보기: ‘실행’을 누르세요. POST /signup에 {"username": "ada", "password": "correct horse"}를 전송하세요. 상태 코드 201과 {"username": "ada"}를 받습니다. 같은 본문에서 "username": "bob"으로 바꾸어 전송하세요. 이제 GET /debug/users/ada를 전송한 다음 GET /debug/users/bob을 전송하세요. 각 passwordHash는 문자 32개, 콜론 하나, 그리고 문자 128개로 이루어져 있습니다. ada와 bob이 같은 비밀번호를 선택했더라도 두 값은 서로 다릅니다.

직접 해보기

import { randomBytes, scrypt } from 'node:crypto';
import { promisify } from 'node:util';

const scryptAsync = promisify(scrypt);

// 비밀번호를 signup이 저장하는 텍스트로 변환합니다.
// 현재는 비밀번호를 입력한 그대로 유지합니다.
export async function hashPassword(password) {
    return password;
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

인증과 보안의 모든 레슨

직접 연습해 보세요: Express 플레이그라운드