Menu
CoddyTech

비밀번호를 절대 저장하지 않기

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

데이터베이스가 유출되면 입력한 그대로 저장된 모든 비밀번호를 읽을 수 있고, 사람들은 다른 사이트에서도 같은 비밀번호를 사용합니다. 그래서 대신 해시를 저장합니다. 해시는 비밀번호로부터 계산된 값으로, 원래 비밀번호로 되돌릴 수 없습니다.

비밀번호를 처리하기 위해 Node는 crypto.scrypt를 제공합니다. 의도적으로 느리게 작동하므로, 수백만 개의 비밀번호를 추측하려면 공격자가 몇 시간이 걸립니다. 해싱하기 전에 섞어 넣는 무작위 바이트인 솔트를 사용하면 같은 비밀번호를 사용하는 두 사람도 서로 다른 해시를 얻게 됩니다. 솔트는 비밀이 아니므로 해시 옆에 저장합니다.

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

const scryptAsync = promisify(scrypt);

const salt = randomBytes(16).toString('hex');
const key = await scryptAsync('pin 4821', salt, 32);
console.log(key.toString('base64'));

promisify는 scrypt의 콜백을 await할 수 있는 프라미스로 바꿉니다.

challenge icon

챌린지

쉬움
  • passwords.js에서 hashPassword(password)가 salt:hash를 반환하도록 하세요. 솔트는 16개의 무작위 바이트로, scrypt 키는 64바이트로 만들고, 둘 다 16진수로 표현합니다.
  • GET /debug/users/:username은 회원 가입 시 저장된 내용을 보여 줍니다.

실행을 누르세요. {"username": "ada", "password": "correct horse"}를 사용해 POST /signup 요청을 보내고, 이어서 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실력 점검

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

인증과 보안의 모든 레슨