カテゴリ: Spring認証(Spring Security) 更新日: 2026/01/11

パスワードをハッシュ化する理由とは?セキュリティ対策の基本をSpring Securityで学ぼう

パスワードをハッシュ化する理由
パスワードをハッシュ化する理由

新人と先輩の会話形式で理解しよう

新人

「先輩、パスワードってデータベースにそのまま保存してもいいんですか?」

先輩

「それは絶対にダメだよ。パスワードは必ずハッシュ化して保存するんだ。」

新人

「ハッシュ化って暗号化とどう違うんですか?」

先輩

「似ているけどまったく違う仕組みなんだ。詳しく説明するね。」

1. パスワードをハッシュ化するとはどういうことか?

1. パスワードをハッシュ化するとはどういうことか?
1. パスワードをハッシュ化するとはどういうことか?

ハッシュ化とは、あるデータ(この場合はパスワード)を一方向の関数で変換して、元に戻せない形にする処理のことです。暗号化とは違い、ハッシュ化されたデータは復号することができません。

たとえば「password123」という文字列をハッシュ関数に通すと、ef92b778bafe771e89245b89...のような結果になります。この結果は、同じ入力をしても毎回違う文字列になるようにもできます(ソルトを使う)。

この仕組みは、「セキュリティ対策」として非常に重要で、Spring Securityでも標準で使われています。「パスワード ハッシュ化」は、現代のWebアプリ開発における基本中の基本です。

2. なぜパスワードをそのまま保存してはいけないのか?

2. なぜパスワードをそのまま保存してはいけないのか?
2. なぜパスワードをそのまま保存してはいけないのか?

パスワードをそのまま保存することは「平文保存」と呼ばれ、極めて危険な行為です。データベースが不正アクセスされた場合、パスワードがすべて漏れてしまうことになります。

たとえば、次のようにパスワードを保存していたとします。


@Entity
public class User {
    private String username;
    private String password; // 平文保存(これは絶対に避けるべき)
}

このような実装では、たとえデータベースが暗号化されていたとしても、攻撃者が復号キーを手に入れたらパスワードが全て見えてしまいます。これでは「セキュリティ対策」とは言えません。

そこで、ハッシュ化の出番です。Spring Securityを使えば、パスワードのハッシュ化は簡単に実装できますし、強固な「パスワード ハッシュ化」が実現できます。

3. ハッシュ関数の特徴と安全性

3. ハッシュ関数の特徴と安全性
3. ハッシュ関数の特徴と安全性

ハッシュ関数は、「一方向性」と「衝突耐性」を持った特別な関数です。「一方向性」とは、入力から出力を計算することはできるけれど、出力から入力を逆算することができないという意味です。これにより、パスワードをハッシュ化した結果から、元のパスワードを割り出すことができなくなります。

また、「衝突耐性」とは、異なるデータが同じハッシュ値になること(ハッシュの衝突)が起きにくいという性質です。これも「セキュリティ対策」の重要な要素です。

さらに安全性を高めるために使われるのが「ソルト(salt)」です。ソルトとは、パスワードに付け加えるランダムな文字列のことです。同じパスワードでもソルトを付ければ異なるハッシュ値になります。

たとえば、次のようなソルトを使ったハッシュの概念です。


String password = "mypassword";
String salt = "abc123";
String salted = password + salt;
String hashed = hashFunction(salted);

このように「ハッシュ関数」と「ソルト」の組み合わせで、安全性が大幅に高まります。Spring Security パスワード管理でもこの考え方が基本に組み込まれています。

4. Spring Securityでのハッシュ化の方法

4. Spring Securityでのハッシュ化の方法
4. Spring Securityでのハッシュ化の方法

Spring Securityでは、BCryptというハッシュ関数を使った仕組みが標準で用意されています。BCrypt ハッシュ化は、計算コストが高くなるよう設計されているため、パスワードクラックに時間がかかる特徴があります。

開発環境がpleiades + Gradleの場合、Spring Securityの依存関係を追加することでBCryptPasswordEncoderが利用可能になります。


import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class PasswordEncoderExample {
    public static void main(String[] args) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String rawPassword = "secret123";
        String encodedPassword = encoder.encode(rawPassword);

        System.out.println("ハッシュ化されたパスワード: " + encodedPassword);
    }
}

ハッシュ化されたパスワード: $2a$10$7Q1zBsH0gPvuz7lAjv3WTO...

このコードでは、encode()メソッドで安全にパスワードをハッシュ化しています。同じ文字列を毎回ハッシュ化しても異なる結果になるのは、BCryptが内部でソルトを自動生成してくれるためです。

次は、Spring MVC(@Controller使用)でユーザー登録時にハッシュ化を行う例です。


@Controller
public class SignupController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @PostMapping("/signup")
    public String register(@ModelAttribute User user) {
        String hashed = passwordEncoder.encode(user.getPassword());
        user.setPassword(hashed);
        userRepository.save(user);
        return "redirect:/login";
    }
}

Spring Security パスワード管理では、このような形でBCryptを活用し、安全な認証処理が実現されます。

5. ハッシュ化と暗号化の違い

5. ハッシュ化と暗号化の違い
5. ハッシュ化と暗号化の違い

ハッシュ化と暗号化は似ているようで、目的も使い方も異なります。初心者の方にとっては混同しやすい部分なので、ここでしっかり区別しておきましょう。

まず、暗号化とは「元に戻せる」処理です。暗号化されたデータは、専用の鍵(キー)を使うことで復号することができます。たとえば、メールの内容やファイルなどを特定の相手にだけ読ませたい場合に使います。

一方、ハッシュ化は「元に戻せない」処理です。パスワードのように、比較だけできればよく、元の値を復元する必要がないケースで使います。

例えるなら、「暗号化」は南京錠をかけて後から鍵で開けられる仕組み、「ハッシュ化」は粉々に砕いたガラスのように元に戻せない仕組みです。

ハッシュ化されたパスワードは、ログイン時に同じハッシュ関数で変換した結果を比較することで認証します。


BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
if (encoder.matches(inputPassword, storedHashedPassword)) {
    // 認証成功
} else {
    // 認証失敗
}

このようにして、Spring Security パスワード管理では、matches()メソッドを使って、ハッシュ値同士の比較による認証処理を行います。これにより、データベース内のパスワードが万が一漏洩しても、元の値を知られるリスクは大幅に下がります。

6. より強力なハッシュアルゴリズム「Argon2」の紹介

6. より強力なハッシュアルゴリズム「Argon2」の紹介
6. より強力なハッシュアルゴリズム「Argon2」の紹介

パスワードのハッシュ化に使われる代表的なアルゴリズムとして、BCryptが一般的ですが、さらに高い安全性を追求する場面では「Argon2 ハッシュ」というアルゴリズムが注目されています。

Argon2は、パスワードハッシュの国際コンペ「Password Hashing Competition(PHC)」で最優秀に選ばれたアルゴリズムで、計算コストだけでなく、メモリコスト並列性も加味して設計されています。これにより、GPUなどによる総当たり攻撃にも耐性が高くなります。

ただし、現時点(2025年)ではSpring Securityの標準機能としてはArgon2は提供されていません。そのため、Argon2を使うには外部ライブラリやカスタム実装が必要ですが、本記事ではSpring Securityの範囲に限定し、BCryptの理解を優先します。

しかしながら、将来的にSpring Security ハッシュ処理が拡張される可能性を考慮し、Argon2 ハッシュも理解しておくことは非常に重要です。

7. パスワードハッシュ化を使ったセキュアなログイン処理の流れ

7. パスワードハッシュ化を使ったセキュアなログイン処理の流れ
7. パスワードハッシュ化を使ったセキュアなログイン処理の流れ

パスワードを安全に管理するためには、ハッシュ化された値を使ってログイン処理を行う必要があります。ここでは、Spring Security ハッシュ処理を使ったログイン処理の流れを整理します。

ユーザーがログインフォームにIDとパスワードを入力したとき、Spring Securityは以下のように動作します。

  1. フォームの入力内容をUsernamePasswordAuthenticationTokenとして受け取る。
  2. ユーザー名に一致するユーザー情報をデータベースから取得する。
  3. 入力されたパスワードと、保存されているハッシュ値をBCryptPasswordEncoder.matches()で比較する。
  4. 一致していれば認証成功。セッションを開始し、アプリケーション内の保護されたリソースへのアクセスを許可する。

この一連の処理は、Spring SecurityのAuthenticationManagerUserDetailsServiceなどを通じて自動的に行われるため、開発者がすべてを手動で実装する必要はありません。

ログイン処理の安全性を確保するために、パスワード ハッシュ化を確実に実装しておくことが前提条件です。

8. ハッシュ化の実装でよくあるミスとその防止策

8. ハッシュ化の実装でよくあるミスとその防止策
8. ハッシュ化の実装でよくあるミスとその防止策

最後に、ハッシュ化 ミスによってセキュリティが弱くなるケースをいくつか紹介し、それぞれの対策を解説します。

① パスワードをハッシュ化せずに保存してしまう

もっとも基本的なミスです。新規登録時にハッシュ処理を忘れてしまうと、平文のままデータベースに保存されてしまいます。これを防ぐためには、サービス層@Controller内で明示的にハッシュ化処理を記述する必要があります。


@Controller
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @PostMapping("/register")
    public String register(@ModelAttribute User user) {
        String encoded = passwordEncoder.encode(user.getPassword());
        user.setPassword(encoded); // ハッシュ化して保存
        userRepository.save(user);
        return "redirect:/login";
    }
}

② 同じパスワードで同じハッシュが生成される

固定されたソルトやハッシュ関数を使うと、同じパスワードを使っているユーザーが同じハッシュ値になってしまいます。BCryptでは、内部で自動的にソルトを付与してくれるため、このミスを防げます。

③ 認証時にハッシュ化せずに直接比較してしまう

ログイン時、入力されたパスワードをハッシュ化せずにDBの値とequals()などで比較してしまうケースです。必ずBCryptPasswordEncoder.matches()を使いましょう。


if (encoder.matches(rawPassword, storedHash)) {
    // 正常認証
}

④ ハッシュアルゴリズムの選定ミス

MD5やSHA-1など、現在では脆弱とされるアルゴリズムを使うのもミスの一つです。現代ではBCryptPBKDF2Argon2などが推奨されています。

まとめると、パスワード ハッシュ化はセキュリティ対策として欠かせない技術であり、正しい実装と安全なアルゴリズムの選定が求められます。Spring Securityの仕組みを活用すれば、これらのミスを防ぎながら、堅牢なログイン処理を構築することが可能です。

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

パスワードをハッシュ化する理由は何ですか?

パスワードをハッシュ化する理由は、セキュリティ対策の一環として、万が一データベースが不正アクセスされた場合に、元のパスワードが漏洩しないようにするためです。ハッシュ化されたパスワードは元に戻せないので安全性が高まります。
コメント
コメント投稿は、ログインしてください

まだ口コミはありません。

カテゴリの一覧へ
新着記事
New1
Spring認証(Spring Security)
Spring BootでCORSを設定する方法を完全解説!初心者でもわかるセキュリティ対策
New2
Spring認証(Spring Security)
パスワードをハッシュ化する理由とは?セキュリティ対策の基本をSpring Securityで学ぼう
New3
SpringのWeb開発(Spring MVC)
HTTPリクエストとレスポンスの基本を完全解説!Spring MVC初心者がWeb通信の仕組みをやさしく理解
New4
Spring認証(Spring Security)
ブラウザからのフォーム送信とは?HTTPリクエストの基礎を初心者向けに解説!
人気記事
No.1
Java&Spring記事人気No1
SpringのWeb開発(Spring MVC)
ルーティングとは?基本概念(Spring MVCのURL制御を理解)
No.2
Java&Spring記事人気No2
Thymeleaf
Thymeleaf とは?初心者向けにThymeleafの基本を徹底解説
No.3
Java&Spring記事人気No3
Springの基本
application.properties と YAML の基本をやさしく解説!初心者向けSpring Boot設定ファイル入門
No.4
Java&Spring記事人気No4
Springの基本
Spring Bootのデフォルトログ設定を徹底解説(Logback / SLF4J)
No.5
Java&Spring記事人気No5
Springの基本
Spring Bootの環境変数の設定方法をやさしく解説!初心者向けapplication.propertiesの使い方
No.6
Java&Spring記事人気No6
SpringのWeb開発(Spring MVC)
ループ処理(th:each)の基本を完全ガイド!Thymeafの繰り返し処理の使い方
No.7
Java&Spring記事人気No7
SpringのDB操作
JPAの標準クエリメソッド(findById, findAll)を完全解説!初心者でもわかるデータ取得の基本
No.8
Java&Spring記事人気No8
Spring認証(Spring Security)
セッション管理の基本(@SessionAttributes)を完全解説!初心者でもわかるセッションの仕組み