← NestJS コース
19. パスワードのハッシュ化 — bcrypt
パスワードを平文のまま DB に保存するのは厳禁です。漏えいした瞬間に全ユーザーのパスワードが読めてしまうためです。代わりに bcrypt のようなハッシュ関数で不可逆な文字列に変換して保存し、ログイン時は入力値を同じ関数にかけて照合します。NestJS では bcrypt パッケージの hash() で保存用の値を作り、compare() で照合します。
実務ではユーザー登録時に bcrypt.hash(平文, saltRounds) を呼び、返ってきた文字列を保存します。bcrypt はハッシュごとに異なるソルト(ランダムな付加文字列)を自動で混ぜるため、同じパスワードでも保存値は毎回変わり、レインボーテーブル攻撃を防げます。照合は元の平文を取り出すのではなく compare() に「入力した平文」と「保存済みハッシュ」を渡して真偽を得ます。
つまずきポイントは saltRounds の値です。大きいほど安全ですが計算が重くなるため、10 前後が定番です。また自前で MD5 や SHA-256 を使ってハッシュ化しようとするのは誤りで、これらは高速すぎて総当たりに弱いため、必ずパスワード専用の bcrypt や argon2 を使います。
サンプルコード(フレームワーク環境が必要なため表示のみ)
import { Injectable } from "@nestjs/common";
import * as bcrypt from "bcrypt";
@Injectable()
export class AuthService {
private readonly saltRounds = 10;
// 登録時: 平文をハッシュ化して保存用の文字列を得る
async hashPassword(plain: string): Promise<string> {
return bcrypt.hash(plain, this.saltRounds); // ソルトは自動で付与
}
// ログイン時: 入力とハッシュを照合(平文には戻さない)
async verify(plain: string, hashed: string): Promise<boolean> {
return bcrypt.compare(plain, hashed);
}
}
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗