Javaでのストレッチングとは?安全なパスワード管理のための基本技術

こんにちは。ゆうせいです。

前回「ハッシュ化」についてお話ししましたね。今回はその続きとして、「ストレッチング」という技術について詳しく解説していきます。

ストレッチングは、特にパスワードの安全性を高めるために重要なテクニックです。「ハッシュ化だけじゃダメなの?」と思った方、ぜひ続きを読んでみてください!


ストレッチングとは何か?

定義と目的

ストレッチング(Stretching)とは、パスワードのハッシュ化を何度も繰り返すことで、計算を重くして攻撃者の総当たり攻撃(ブルートフォース)を防ぐ技術です。

簡単に言うと、「パスワードのハッシュを1回で終わらせるんじゃなくて、1000回とか繰り返して、わざと時間をかける」ことです。


例え話で理解しよう

例えるなら、金庫の鍵を1回だけ回して開ける代わりに、「1000回ガチャガチャ回さないと開かない金庫」にするイメージです。

攻撃者にとっては、1回の鍵開けで済むのと、1000回かかるのとでは、手間がまるで違いますよね?


Javaでのストレッチング方法

標準APIでも「手動」でストレッチングは実現可能です。以下にSHA-256を使った簡易な例を紹介します。

自作ストレッチングのコード例

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class StretchingExample {
    public static void main(String[] args) {
        String password = "mySecret123";
        String salt = "randomSalt";
        int iterations = 10000;

        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");

            byte[] input = (salt + password).getBytes();

            for (int i = 0; i < iterations; i++) {
                input = md.digest(input);
            }

            // ハッシュ値を16進数に変換
            StringBuilder sb = new StringBuilder();
            for (byte b : input) {
                sb.append(String.format("%02x", b));
            }

            System.out.println("ストレッチング後のハッシュ値: " + sb.toString());

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}


ストレッチングのポイント

項目内容
ソルト必須。ないと意味がない(必ず毎回違う値に)
繰り返し回数多ければ多いほど安全(ただし性能と要相談)
アルゴリズムSHA-256やSHA-512など

もっと安全にするには?

手動でやるよりも、専用のKDF(Key Derivation Function)を使うのがベストです。

代表的なKDF(キー導出関数)

名前特徴
PBKDF2Java標準。ストレッチング回数指定可能
bcrypt遅延性あり。現在も人気
scryptメモリも食わせることでさらに強化される
Argon2最新。パスワードコンペで優勝した実力派

JavaでのPBKDF2の使い方(標準ライブラリ)

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class PBKDF2Example {
    public static void main(String[] args) throws Exception {
        String password = "mySecret123";
        byte[] salt = new byte[16];
        SecureRandom sr = new SecureRandom();
        sr.nextBytes(salt);

        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256); // 65536回、256bit
        SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
        byte[] hash = skf.generateSecret(spec).getEncoded();

        System.out.println("Salt: " + Base64.getEncoder().encodeToString(salt));
        System.out.println("Hash: " + Base64.getEncoder().encodeToString(hash));
    }
}

ここでは:

  • PBEKeySpec: パスワード、ソルト、繰り返し回数、キー長を指定
  • SecretKeyFactory: ハッシュ生成を行うエンジン

手動 vs PBKDF2:どっちが良い?

項目手動SHA-256PBKDF2
安全性中~高高(標準に準拠)
実装の簡単さやや簡単少し複雑
将来性・推奨度やや低(独自実装)高(業界標準)

結論としては、PBKDF2以上のKDFを使うのが圧倒的におすすめです。


まとめと次のステップ

  • ストレッチングはハッシュ処理を何度も繰り返すことで安全性を高める技術
  • Javaでは標準の MessageDigest を使った手動ストレッチングも可能
  • より安全な実装には PBKDF2WithHmacSHA256 を使うべき
  • ソルトは必須。繰り返し回数は1万回以上を目安に

次に学ぶべきこと

  • bcrypt, scrypt, Argon2 の違いと選び方
  • ハッシュ値とともに「どんなソルト・KDF設定だったか」を保存する方法
  • 実際のアプリケーションでの認証フローへの統合

「PBKDF2はわかったけど、bcryptやArgon2も試したい!」という方は、次回そちらを紹介しますのでお楽しみに!

何かコードや概念で引っかかっていたら、遠慮なく質問してくださいね。


セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。