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(キー導出関数)
名前 | 特徴 |
---|---|
PBKDF2 | Java標準。ストレッチング回数指定可能 |
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-256 | PBKDF2 |
---|---|---|
安全性 | 中~高 | 高(標準に準拠) |
実装の簡単さ | やや簡単 | 少し複雑 |
将来性・推奨度 | やや低(独自実装) | 高(業界標準) |
結論としては、PBKDF2以上のKDFを使うのが圧倒的におすすめです。
まとめと次のステップ
- ストレッチングはハッシュ処理を何度も繰り返すことで安全性を高める技術
- Javaでは標準の
MessageDigest
を使った手動ストレッチングも可能 - より安全な実装には
PBKDF2WithHmacSHA256
を使うべき - ソルトは必須。繰り返し回数は1万回以上を目安に
次に学ぶべきこと
bcrypt
,scrypt
,Argon2
の違いと選び方- ハッシュ値とともに「どんなソルト・KDF設定だったか」を保存する方法
- 実際のアプリケーションでの認証フローへの統合
「PBKDF2はわかったけど、bcryptやArgon2も試したい!」という方は、次回そちらを紹介しますのでお楽しみに!
何かコードや概念で引っかかっていたら、遠慮なく質問してくださいね。
セイ・コンサルティング・グループの新人エンジニア研修のメニューへのリンク
投稿者プロフィール
