コース一覧
    Node.js認証・本番運用
    パスワードハッシュ

    Node.js認証・本番運用

    認証、認可、フロントエンド連携、本番運用を学び、Node.jsで保守可能なサービスを完成させられるようにします。

    1
    認証のきほん
    01. 認証と認可15分
    02. パスワードハッシュ15分
    03. ログインとトークン15分
    04. 保護ルート15分
    05. 本人のものだけ15分
    06. つくる:認証完備20分
    07. 第7章クイズ10分
    2
    総合制作
    01. fleama API完成20分
    02. Reactと接続する20分
    03. サーバーで常駐させる20分
    04. 自由拡張20分
    05. 完成と次のステップ15分

    パスワードハッシュ

    そのまま保存してはいけない

    会員登録を作るとき、いちばんやってはいけないのがこれです。

    JavaScript

    db.prepare("INSERT INTO users (name, password) VALUES (?, ?)").run(name, password);

    プレースホルダは正しく使っています。ですがパスワードがそのまま保存されています。

    データベースが漏れたとき、全員のパスワードがそのまま読まれます。しかも多くの人は同じパスワードを他のサービスでも使っているので、被害は fleama の中では終わりません。

    元に戻せない形にする

    ハッシュ化は、値を元に戻せない形に変える処理です。

    JavaScript

    const crypto = require("crypto");
    const hashed = crypto.scryptSync(password, salt, 32).toString("hex");

    同じ入力からは必ず同じ結果が出ます。逆に、結果から元のパスワードを求めることはできません。

    保存するのはこの結果だけです。ログインのときは、送られてきたパスワードを同じ手順でハッシュ化して、保存してあるものと一致するかを見ます。元に戻す必要はありません。

    salt を混ぜる

    salt は、ハッシュ化のときに一緒に混ぜる文字列です。

    これが無いと、同じパスワードを使っている人は同じ結果になります。漏れたときに「この 2 人は同じパスワードだ」と分かってしまいますし、よくあるパスワードの結果を並べた表と照合されると元が割れます。

    利用者ごとに違う salt を混ぜれば、同じパスワードでも結果が変わります。salt 自体は秘密ではないので、ハッシュと一緒に保存して構いません。

    比べ方にも作法がある

    JavaScript

    if (hashed === stored) { ... }

    動きますが、より安全な比べ方があります。

    JavaScript

    crypto.timingSafeEqual(Buffer.from(hashed), Buffer.from(stored));

    === は違いが見つかった時点で比較をやめるので、一致した文字数によって処理時間がわずかに変わります。その差を測って 1 文字ずつ当てていく攻撃があります。timingSafeEqual は最後まで比べるので、時間から情報が漏れません。

    返すときも気をつける

    登録の応答に、ハッシュを含めてはいけません。

    JavaScript

    res.status(201).json({ id: user.id, name: user.name });

    第3章から繰り返してきた「返すものは選ぶ」が、いちばん効く場面です。

    手を動かす

    演習では、会員登録の処理を書きます。保存する形と、返す形の両方に気を配ってください。

    要件

    1. パスワードをハッシュ化して password_hash 列に保存する(平文は保存しない)
    2. stored は保存された {id, name, password_hash} を返す
    3. response は {id, name} だけにして、ハッシュも平文も含めない

    ヒント

    初期コードは `password` をそのまま保存しています。ここが直すところです

    ハッシュ化は `crypto.scryptSync(password, salt, 32).toString("hex")` です

    `response` は `stored` をそのまま渡さず、`id` と `name` だけの新しいオブジェクトにします

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/08/10

    関連レッスン

    • ログインとトークン

      ログインAPIがトークンを返すようにし、トークンを発行できるようになります。

    • 保護ルート

      出品と購入をログイン必須にし、トークンが要るAPIを作れるようになります。

    • 本人のものだけ

      自分の出品だけ編集できるようにし、認可チェックを書けるようになります。

    • つくる:認証完備

      登録からログイン・出品・編集までを通し、認証を備えたAPIを完成できるようになります。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • プレースホルダSQL の `?` 部分にあとから値を入れる仕組み
    • パスワードDBが漏洩しても元のパスワードがわからないようにするため。
    • データベースデータを構造化して保存する仕組み
    • ハッシュ化元に戻せない一方向変換でパスワードを保管
    • 処理計算や代入を表す長方形
    main.js
    エディタを読み込んでいます

    メモ

    パスワードハッシュ

    ⌘S で保存