※開発の最終段階でハッシュ化することをお薦めします。
今回は、Javaで安全にパスワードをハッシュ化する方法について、新人エンジニア向けに解説していきます。
「パスワードってどうやって暗号化すればいいの?」
「ハッシュって何?戻せるの?」
…そんなあなたの疑問に、ライブラリの使い方から安全な設計の考え方まで、しっかり説明していきます!
なぜパスワードをハッシュ化する必要があるの?
パスワードをそのまま保存してしまうと、万が一データベースが流出したときに、利用者全員のパスワードが漏れてしまいます。
そのため、次のような仕組みが必要です:
- ハッシュ化:元の文字列から別の文字列に変換(復元不可)
- ソルト:ランダムな追加文字列でレインボーテーブル攻撃を防ぐ
- ストレッチング:繰り返しハッシュして総当たり攻撃に耐える
Apache Commons Codecとは?
Apache Commons Codecは、Javaでハッシュやエンコードを簡単に行えるライブラリです。
代表的なハッシュ関数
アルゴリズム | 特徴 |
---|---|
MD5 | 古くて高速、非推奨 |
SHA-1 | こちらも非推奨 |
SHA-256 | 安全性が高く、CRYPTRECにも掲載されている推奨アルゴリズム |
導入手順
- 公式サイトから最新版の
.jar
をダウンロード WEB-INF/lib
フォルダに配置- Javaで
import org.apache.commons.codec.digest.DigestUtils;
を追加
サンプル①:SHA-256でパスワードをハッシュ化する
import org.apache.commons.codec.digest.DigestUtils;
public class DigestUtilsTest {
public static void main(String[] args) {
String plainPassword = "123456789";
// シンプルなハッシュ
String hashed = DigestUtils.sha256Hex(plainPassword);
System.out.println("ハッシュ(単純): " + hashed);
// ソルト付きハッシュ(推奨)
String salt = "randomSalt123";
String saltedHash = DigestUtils.sha256Hex(plainPassword + salt);
System.out.println("ハッシュ(ソルト付き): " + saltedHash);
}
}
実行結果の例:
ハッシュ(単純): 15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225
ハッシュ(ソルト付き): ab03db0c39851456931b33c525bf70aa4998172865c9adebf930894c4fe8e51f
注意! 単純なハッシュはレインボーテーブル(逆引き辞書攻撃)で破られます。
ソルト(ランダムな文字列)を必ず加えましょう!
サンプル②:ストレッチング(ハッシュの繰り返し)
import org.apache.commons.codec.digest.DigestUtils;
public class DigestUtilsTest2 {
public static void main(String[] args) {
String password = "123456789";
// ストレッチング(10000回)
for (int i = 0; i < 10000; i++) {
password = DigestUtils.sha256Hex(password);
}
System.out.println("ストレッチング結果: " + password);
}
}
ストレッチングとは?
同じデータに繰り返しハッシュをかけることで、攻撃の計算コストを上げる技術です。
よくある質問(FAQ)
Q1:ハッシュ化されたパスワードは元に戻せますか?
→ 戻せません!
ハッシュは「一方向関数」と呼ばれ、暗号化とは異なり復号はできません。
Q2:ログイン時のパスワード確認はどうするの?
→ ユーザーが入力したパスワードに同じソルトとハッシュ処理をかけて、データベースのハッシュ値と比較します。
Q3:ソルトはどう作る?
import java.security.SecureRandom;
public class SaltGenerator {
public static String generateSalt(int length) {
SecureRandom random = new SecureRandom();
StringBuilder salt = new StringBuilder(length);
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (int i = 0; i < length; i++) {
salt.append(chars.charAt(random.nextInt(chars.length())));
}
return salt.toString();
}
}
まとめ
機能 | 説明 |
---|---|
DigestUtils.sha256Hex() | 文字列をSHA-256でハッシュ化 |
ソルト | 同じパスワードでも違うハッシュにするための追加文字列 |
ストレッチング | 複数回ハッシュで安全性アップ |
保存すべき情報 | ハッシュ値とソルト(ユーザーごとに異なるもの) |
今後の学習の指針
- SHA-512やPBKDF2、bcryptなどのより安全なハッシュ技術にも触れてみよう
- ソルトとストレッチングの設計パターンを比較してみよう
- 認証処理を行うサーバーサイドのアーキテクチャ(Spring Securityなど)にも挑戦してみよう
- OWASP(セキュリティのベストプラクティス)にも目を通そう!
セキュリティは「今できていればOK」ではなく、「未来にも通用すること」が大切です。
今日学んだハッシュの知識を活かして、安全で信頼されるアプリケーションを作っていきましょう!
質問があればいつでもどうぞ!