カテゴリ: Java 更新日: 2026/04/12

JavaのSecureRandomクラスの使い方を完全ガイド!初心者でもわかるセキュアな乱数生成

SecureRandomクラス
SecureRandomクラス

先生と生徒の会話形式で理解しよう

生徒

「Javaでセキュリティの高い乱数を生成する方法ってありますか?」

先生

「はい、JavaにはSecureRandomというクラスが用意されています。このクラスを使うことで、暗号レベルのセキュアな乱数を生成できます。」

生徒

「普通のRandomクラスとどう違うんですか?」

先生

「良い質問ですね。Randomクラスは一般的な用途で使う乱数を生成しますが、セキュリティが求められる場合はSecureRandomを使います。それでは、具体的な使い方を見ていきましょう!」

1. SecureRandomクラスとは?

「1. SecureRandomクラスとは?」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

1. SecureRandomクラスとは?
1. SecureRandomクラスとは?

Javaでセキュリティの高い乱数を生成したい場合に登場するのがSecureRandomクラスです。見た目は普通の乱数と同じように使えますが、内部では予測がとても難しい仕組みで乱数を作り出します。そのため、パスワードやトークン、認証コードなど、セキュリティが重要な場面で利用されます。まずはインポートして使える形にしましょう。


import java.security.SecureRandom;

「普通のRandomではダメなの?」と疑問に思う人も多いですが、Randomは予測される可能性があります。一方、SecureRandomは予測がほぼ不可能なので、安全な乱数が必要なアプリケーションでは標準的に使われています。

簡単なサンプル(まずは動かしてみる)


public class SimpleSecureRandom {
    public static void main(String[] args) {
        SecureRandom sr = new SecureRandom();
        int number = sr.nextInt(10); // 0〜9 の乱数
        System.out.println("セキュアな乱数: " + number);
    }
}

上の例では、0〜9の中からランダムに1つ数字を取り出しています。見た目は簡単ですが、中身はしっかりとセキュアな乱数です。普段のJavaプログラムと同じ感覚で書けるので、初心者でも安心して使えます。

2. SecureRandomの基本的な使い方

2. SecureRandomの基本的な使い方
2. SecureRandomの基本的な使い方

SecureRandomを使った乱数の生成はとてもシンプルです。まずは、最も基本的な数字の乱数を作る例から見てみましょう。難しい設定は不要で、インスタンスを作って数字を取得するだけでOKです。


import java.security.SecureRandom;

public class SecureRandomExample {
    public static void main(String[] args) {
        SecureRandom secureRandom = new SecureRandom();  // セキュアな乱数生成器
        int number = secureRandom.nextInt(10);           // 0〜9 の中からランダムで1つ
        System.out.println("セキュアな乱数: " + number);
    }
}

実行結果


セキュアな乱数: 7

このサンプルでは、必ず0〜9の範囲で整数が1つ出力されます。見た目は普通の乱数ですが、内部では予測しづらい仕組みで数字が作られており、認証コードや使い捨てトークンのような安全性が求められる用途に向いています。

もし、複数回乱数を取りたい場合も同じ方法で簡単に実装できます。下の例では3回連続で乱数を出力しています。


public class MultiSecureRandom {
    public static void main(String[] args) {
        SecureRandom sr = new SecureRandom();
        for (int i = 0; i < 3; i++) {
            System.out.println("乱数: " + sr.nextInt(10));
        }
    }
}

初心者でも扱いやすい書き方なので、まずはコピーして実行してみるのがおすすめです。数値がランダムに切り替わる様子を見るだけでも、SecureRandomの使い方が自然と理解できるようになります。

3. バイト配列を使った乱数の生成

3. バイト配列を使った乱数の生成
3. バイト配列を使った乱数の生成

SecureRandomクラスは、数値だけでなく「バイト配列」にも直接乱数を書き込むことができます。言い換えると、指定した長さの入れ物(配列)に、セキュアなランダム値をまとめて詰め込める仕組みです。この方法は、ランダムなトークンや暗号キーを作成したい場面で特によく使われます。「整数をひとつ作る」のではなく、「決まった長さの生データをまとめて作る」イメージです。


import java.security.SecureRandom;

public class SecureRandomBytes {
    public static void main(String[] args) {
        SecureRandom secureRandom = new SecureRandom();
        byte[] randomBytes = new byte[16];        // 16バイト分の入れ物を用意
        secureRandom.nextBytes(randomBytes);      // 配列にランダム値を詰める

        // 中身を16進数で表示(初心者でも結果が見やすい形)
        System.out.print("生成されたバイト配列: ");
        for (byte b : randomBytes) {
            System.out.printf("%02x ", b);
        }
    }
}

実行結果


生成されたバイト配列: 3e a5 7f d1 2b 4c 93 20 e4 7a c8 9f 1e 7b a0 5d 

このプログラムでは、16個ぶんのランダムなバイト値をまとめて取得し、結果を16進数で表示しています。バイト配列を使うメリットは、「長さが決まったセキュアなデータ」を手軽に作れることです。パスワード生成、APIキーの材料、セッションIDの元データなど、セキュリティが大切な処理で役に立ちます。実際に動かしてみると、何度実行しても毎回違う値になる様子が分かり、乱数生成の仕組みがよりイメージしやすくなるはずです。

4. SecureRandomのシード値について

「4. SecureRandomのシード値について」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

4. SecureRandomのシード値について
4. SecureRandomのシード値について

SecureRandomには「シード」と呼ばれる初期値があります。通常は自動的に安全なシードが設定されますが、あえて自分でシード値を指定すると、毎回同じ乱数を再現できます。「テストでは何度実行しても同じ結果にしたい」という場面で役立ちます。

イメージとしては、乱数のスタート地点を自分で決める感じです。セキュリティ上、実際のシステムでは自動シードで問題ありませんが、学習や動作確認にはとても便利な仕組みです。


import java.security.SecureRandom;

public class SecureRandomWithSeed {
    public static void main(String[] args) {
        byte[] seed = {1, 2, 3, 4, 5};              // 好きなシード値を準備
        SecureRandom secureRandom = new SecureRandom(seed);
        
        // 何度実行しても同じ結果になる
        System.out.println(secureRandom.nextInt(100));
        System.out.println(secureRandom.nextInt(100));
        System.out.println(secureRandom.nextInt(100));
    }
}

実行結果


41
12
87

このコードを何度実行しても、上と同じ数字が表示されます。これは、同じシード値から同じ乱数列が生まれているためです。テストやデバッグで「結果が変わると困る」ときに、とても便利なテクニックです。まずは試しにシードの値を変えてみて、結果がどう変わるか確認してみましょう。

5. SecureRandomを使ったパスワード生成の例

5. SecureRandomを使ったパスワード生成の例
5. SecureRandomを使ったパスワード生成の例

最後に、SecureRandomを使ったパスワード生成の実装例を紹介します。アルファベットと数字を組み合わせたランダムなパスワードを生成します。


import java.security.SecureRandom;

public class SecureRandomPassword {
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    private static final int PASSWORD_LENGTH = 12;

    public static void main(String[] args) {
        SecureRandom secureRandom = new SecureRandom();
        StringBuilder password = new StringBuilder();

        for (int i = 0; i < PASSWORD_LENGTH; i++) {
            int index = secureRandom.nextInt(CHARACTERS.length());
            password.append(CHARACTERS.charAt(index));
        }

        System.out.println("生成されたパスワード: " + password);
    }
}

実行結果


生成されたパスワード: Xy8Z1dAe4QpB

このプログラムでは、ランダムに選んだ12文字のパスワードを生成します。SecureRandomを使うことで、セキュリティの高いパスワードを生成することが可能です。

6. 初期化とアルゴリズムの選び方(getInstanceStrongの注意点)

6. 初期化とアルゴリズムの選び方(getInstanceStrongの注意点)
6. 初期化とアルゴリズムの選び方(getInstanceStrongの注意点)

new SecureRandom() は通常の用途に十分です。より強度の高い実装を明示したい場合は SecureRandom.getInstanceStrong() を使えますが、環境によってはエントロピー待ちでブロックする可能性があるため、高負荷・低レイテンシ要件の本番処理では慎重に評価しましょう。まずはデフォルトで問題ないかを確認し、必要に応じてプロバイダやアルゴリズムをログに出して観測するのがおすすめです。


import java.security.SecureRandom;

public class InitAndAlgo {
    public static void main(String[] args) throws Exception {
        // 推奨: まずはデフォルト
        SecureRandom def = new SecureRandom();
        System.out.println("Default: " + def.getAlgorithm() + " / " + def.getProvider().getName());

        // 強力だがブロックの可能性あり: 事前検証が必須
        SecureRandom strong = SecureRandom.getInstanceStrong();
        System.out.println("Strong : " + strong.getAlgorithm() + " / " + strong.getProvider().getName());
    }
}
  • 実装はJDKやOSに依存します。アルゴリズム名・プロバイダ名を把握しておくと運用で役立ちます。
  • ベンチマークと監視を行い、必要に応じてインスタンスの使い分けを検討しましょう。

7. 固定シードはテスト専用:setSeedの正しい理解

「7. 固定シードはテスト専用:setSeedの正しい理解」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

7. 固定シードはテスト専用:setSeedの正しい理解
7. 固定シードはテスト専用:setSeedの正しい理解

固定シードでの初期化(例:new SecureRandom(seed))は再現性重視のテスト用です。本番のセキュアな乱数生成では固定シードを使わないでください。setSeed() は「置き換え」ではなく既存の状態に追加で混ぜるためのものとして設計されています(追加のエントロピーを与える用途)。


import java.security.SecureRandom;
import java.nio.charset.StandardCharsets;

public class SeedingBestPractice {
    public static void main(String[] args) {
        SecureRandom sr = new SecureRandom(); // 本番はこれで十分
        // 追加のエントロピーが外部から得られる場合のみ、追加入力として混ぜる
        byte[] extraEntropy = "human-typed-rare-event".getBytes(StandardCharsets.UTF_8);
        sr.setSeed(extraEntropy); // 追加ミキシング(必須ではない)
        System.out.println(sr.nextInt());
    }
}
  • 本番で固定シードはNG(予測可能になります)。
  • setSeed() は追加エントロピーの混入用途。通常は不要です。

8. トークンやキーの長さと安全なエンコード(Base64 / Hex)

8. トークンやキーの長さと安全なエンコード(Base64 / Hex)
8. トークンやキーの長さと安全なエンコード(Base64 / Hex)

セッションIDやCSRFトークンなどの秘密値には、最低でも16バイト(128ビット)以上、推奨は32バイト(256ビット)の乱数を使い、URLやヘッダで扱いやすい形式にエンコードします。URLに載せる場合は Base64 URL-safe が便利です。ログや可読性重視なら16進表記(Hex)も有効です。


import java.security.SecureRandom;
import java.util.Base64;
// JDK 17+ なら HexFormat も使えます: import java.util.HexFormat;

public class TokenEncoder {
    public static void main(String[] args) {
        SecureRandom sr = new SecureRandom();

        // 推奨サイズ: 32バイト
        byte[] tokenBytes = new byte[32];
        sr.nextBytes(tokenBytes);

        // URL-safe Base64(パディングなし)
        String urlToken = Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes);
        System.out.println("URL-safe token: " + urlToken);

        // Hex(JDK 17+)
        // String hexToken = HexFormat.of().formatHex(tokenBytes);
        // System.out.println("Hex token    : " + hexToken);
    }
}
  • 文字集合を自作すると偏りや実装ミスが起きやすいので、まずは Base64/Hex を検討。
  • 秘匿情報はログ出力・コンソール出力を最小化し、マスキングを徹底しましょう。

9. よくある落とし穴と実践チェックリスト

9. よくある落とし穴と実践チェックリスト
9. よくある落とし穴と実践チェックリスト
  • RandomMath.random()を使わない。 セキュアな乱数は必ず SecureRandom
  • 固定シードはテスト専用。本番では自動シードに任せる。
  • バイト値の「剰余(%)」で文字集合に割り当てると偏りの原因。nextInt(bound) を使う。
  • 十分なバイト長を確保(16〜32バイト)。取り回しは Base64/Hex を使用。
  • 高頻度アクセスではスレッドごとにインスタンスを持つなど、競合による遅延を避ける設計を。

例:6桁のワンタイムコードを均等分布で生成(ゼロ埋め)。


import java.security.SecureRandom;

public class OtpExample {
    public static void main(String[] args) {
        SecureRandom sr = new SecureRandom();
        int code = sr.nextInt(1_000_000); // 0〜999999 の一様乱数
        String otp = String.format("%06d", code); // ゼロ埋めで6桁固定
        System.out.println("OTP: " + otp);
    }
}

まとめ

「まとめ」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

まとめ
まとめ

この記事では、JavaのSecureRandomクラスについて、基本的な使い方から応用例まで詳しく解説しました。SecureRandomは、暗号学的に安全な乱数を生成するためのクラスで、通常のRandomクラスよりも強力なセキュリティが求められる場面で非常に有効です。 例えば、パスワードやAPIキーの生成、トークンの発行など、セキュアなランダムデータが必要なシステムでは必須の機能と言えるでしょう。
SecureRandomは単に乱数を生成するだけでなく、バイト配列やシード値を使った多様な乱数生成も可能です。また、特定のシード値を設定することで再現性のある乱数も生成できるため、テストやデバッグの場面でも役立ちます。

さらに、SecureRandomを使ったパスワード生成の方法を学ぶことで、より安全な認証情報を作成できるスキルが身につきました。この記事を参考にして、セキュリティが重要なプロジェクトにおいてSecureRandomを効果的に活用してください。

パスワード生成のもう一つの例

最後に、もう少し応用的なパスワード生成プログラムを紹介します。特殊文字を含めたパスワードを生成してみましょう。


import java.security.SecureRandom;

public class AdvancedPasswordGenerator {
    private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+";
    private static final int PASSWORD_LENGTH = 16;

    public static void main(String[] args) {
        SecureRandom secureRandom = new SecureRandom();
        StringBuilder password = new StringBuilder();

        for (int i = 0; i < PASSWORD_LENGTH; i++) {
            int index = secureRandom.nextInt(CHARACTERS.length());
            password.append(CHARACTERS.charAt(index));
        }

        System.out.println("強力なパスワード: " + password);
    }
}

実行結果


強力なパスワード: Ab8&xP2#Rt!7gLk$

このプログラムでは、特殊文字を含めた16文字のパスワードを生成します。セキュリティレベルをさらに高めたい場合に活用してください。

先生と生徒の振り返り会話

生徒

「今回SecureRandomクラスについて詳しく学べました。暗号レベルの乱数を使うとセキュリティが向上するんですね!」

先生

「その通りです。SecureRandomを活用すれば、安全なパスワードやトークンの生成が可能になります。セキュリティが求められる開発には必須のスキルですね。」

生徒

nextBytes()nextInt()などのメソッドも便利でした。特にバイト配列を使う方法は新鮮でした。」

先生

「バイト配列を使えば、より多様なセキュリティ用途に対応できます。次は実際のプロジェクトで使ってみてください。」

生徒

「ありがとうございます!これでセキュアなアプリケーションの開発に一歩近づきました!」

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

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

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

JavaのSecureRandomとRandomの違いは何ですか?暗号学的に安全な乱数生成という点で、セキュリティ強度や予測困難性、パスワード生成・APIキー生成・トークン生成・暗号鍵作成などの用途でどう使い分ければよいのかを初心者向けに知りたいです。

SecureRandomは暗号学的に安全な乱数生成に最適化されたJavaのクラスで、予測されにくい乱数を提供します。Randomは一般的な用途向けで、セキュリティ目的のパスワード生成やトークン生成には推奨されません。記事では、セキュアな乱数が必要な場面(パスワード・APIキー・トークン・暗号鍵など)ではSecureRandomを使う、と明確に位置づけています。

SecureRandomの基本的な使い方を知りたいです。Javaで0から9の範囲のセキュアな乱数を生成する考え方や、初心者がつまずきやすいポイントを含めて、乱数生成の流れをわかりやすく教えてください。

SecureRandomの基本は、インスタンスを用意し、範囲を与えて乱数を取り出すことです。記事の例では0から9の範囲を扱い、範囲指定により目的に合った値を得られると説明しています。予測困難でセキュアな乱数を前提に、認証・認可・ログインなど安全性が求められる処理に向くという理解が第一歩になります。

JavaのどこにSecureRandomは含まれていますか?java.securityパッケージの位置づけや、初心者が理解しておくべきインポートの考え方について知りたいです。

記事のとおり、SecureRandomはjava.securityパッケージに含まれます。つまりJava標準のセキュリティ関連APIの一部として提供されており、セキュアな乱数生成を標準機能だけで実現できます。開発時はセキュリティ用途のAPIを扱う意識を持つと、設計段階から安全性を意識しやすくなります。
カテゴリの一覧へ
新着記事
New1
Java
JavaのNotSerializableExceptionを完全解説!初心者でも理解できるシリアライズと例外処理
新規投稿
New2
Spring
Springの@Repositoryアノテーションの使い方を徹底解説!初心者でもわかるSpringフレームワークのデータアクセス
更新記事
New3
Spring
Springの@Componentアノテーションの使い方を徹底解説!初心者でもわかるSpring Boot入門
更新記事
New4
Java
Javaのjava.mathとBigIntegerのintValueメソッドを完全解説!初心者でもわかる数値変換の基本
更新記事
人気記事
No.1
Java&Spring記事人気No1
Servlet
JavaのHttpSessionを徹底解説!初心者でもわかるセッション管理の基本
No.2
Java&Spring記事人気No2
JSP
JSPの基本タグ一覧と使い方まとめ!実務で使えるタグを紹介
No.3
Java&Spring記事人気No3
JSP
JSPでフォームを表示して入力を受け取る基本手順をやさしく解説!初心者向けフォーム処理の入門ガイド
No.4
Java&Spring記事人気No4
Spring
Springの@Serviceアノテーションの使い方を徹底解説!初心者でもわかるSpring フレームワーク入門
No.5
Java&Spring記事人気No5
JSP
JSPでCSSやJSを読み込む基本!外部ファイルのパス指定に注意しよう
No.6
Java&Spring記事人気No6
Spring
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.7
Java&Spring記事人気No7
Spring
Spring Data JPA入門!findAll()やfindBy**()の使い方などデータベース操作の基礎を学ぶ
No.8
Java&Spring記事人気No8
JSP
JSPでif文・for文を使う方法!初心者でもわかるJavaとの違いと使い方