Java SecureRandom 类
上次修改:2025 年 4 月 26 日
SecureRandom 类是 Java 安全包的一部分,用于生成密码学上安全的随机数。它提供了生成安全的随机整数、双精度浮点数和字节数组的方法。
安全随机数生成对于密码学、安全令牌和敏感应用程序至关重要。SecureRandom 使用强大的算法来确保不可预测和高质量的随机性。
SecureRandom 类概述
SecureRandom 扩展了 Random 类,但专为安全关键任务而设计。 它利用系统熵或安全算法来生成适合密码学使用的随机值。
关键方法包括 nextInt、nextDouble 和 nextBytes。虽然比 Random 慢,但它提供卓越的随机性,这对于安全应用程序至关重要。
基本安全随机数生成
此示例演示了 SecureRandom 的基本用法,用于为安全应用程序生成随机整数、双精度浮点数和字节数组。
package com.zetcode;
import java.security.SecureRandom;
public class BasicSecureRandom {
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
// Generate random integer
int randInt = secureRandom.nextInt();
System.out.println("Secure random integer: " + randInt);
// Generate random integer between 0 and 100 (exclusive)
int randIntRange = secureRandom.nextInt(100);
System.out.println("Secure random integer (0-99): " + randIntRange);
// Generate random double
double randDouble = secureRandom.nextDouble();
System.out.println("Secure random double: " + randDouble);
// Generate random byte array
byte[] bytes = new byte[8];
secureRandom.nextBytes(bytes);
System.out.print("Secure random bytes: ");
for (byte b : bytes) {
System.out.printf("%02x", b);
}
System.out.println();
}
}
此程序创建一个 SecureRandom 实例来生成各种随机值。 字节数组以十六进制显示,以提高可读性。
每次执行都会产生不可预测的结果,利用系统熵来实现密码学强度,使其成为安全敏感任务的理想选择。
在范围内生成安全随机数
此示例展示了如何使用 SecureRandom 在特定范围内生成安全随机数,这对于安全令牌生成非常有用。
package com.zetcode;
import java.security.SecureRandom;
public class SecureRandomRange {
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
int min = 10;
int max = 20;
// Generate secure random integer in range [min, max]
int randInt = secureRandom.nextInt(max - min + 1) + min;
System.out.println("Secure random int (" + min + "-" + max + "): " + randInt);
// Generate secure random double in range [min, max)
double randDouble = min + (max - min) * secureRandom.nextDouble();
System.out.println("Secure random double (" + min + "-" + max + "): " + randDouble);
}
}
该程序使用 nextInt 和 nextDouble 生成自定义范围内的数字,确保输出值的密码学安全性。
这种方法适用于安全 PIN 生成或随机密码参数等应用,其中不可预测性至关重要。
生成安全随机字符串
此示例说明了如何使用 SecureRandom 创建随机字符串,非常适合生成安全密码或会话标识符。
package com.zetcode;
import java.security.SecureRandom;
public class SecureRandomString {
private static final String CHARACTERS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
public static String generateSecureString(SecureRandom random, int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int index = random.nextInt(CHARACTERS.length());
sb.append(CHARACTERS.charAt(index));
}
return sb.toString();
}
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
System.out.println("Secure random string (8 chars): " +
generateSecureString(secureRandom, 8));
System.out.println("Secure random string (16 chars): " +
generateSecureString(secureRandom, 16));
}
}
我们定义了一个字符集,并使用 SecureRandom 选择随机字符,构建指定长度的安全字符串,用于敏感用例。
此方法非常适合创建安全令牌或密码,确保高随机性并抵抗安全关键应用程序中的预测。
使用特定算法
此示例演示了如何使用特定的密码学算法配置 SecureRandom,以增强随机数生成的安全性。
package com.zetcode;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
public class SecureRandomAlgorithm {
public static void main(String[] args) {
try {
// Use SHA1PRNG algorithm
SecureRandom sha1prng = SecureRandom.getInstance("SHA1PRNG");
System.out.println("SHA1PRNG random int: " + sha1prng.nextInt());
// Use NativePRNG algorithm
SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG");
System.out.println("NativePRNG random int: " + nativePrng.nextInt());
// Generate secure bytes with NativePRNG
byte[] bytes = new byte[8];
nativePrng.nextBytes(bytes);
System.out.print("NativePRNG bytes: ");
for (byte b : bytes) {
System.out.printf("%02x", b);
}
System.out.println();
} catch (NoSuchAlgorithmException e) {
System.err.println("Algorithm not available: " + e.getMessage());
}
}
}
我们使用诸如 SHA1PRNG 或 NativePRNG 之类的特定算法实例化 SecureRandom,从而可以为特定的安全需求定制随机性。
算法的选择取决于应用程序的要求。 此示例展示了如何处理不可用算法的潜在异常。
播种 SecureRandom
此示例展示了如何手动播种 SecureRandom,这对于测试中的可重现结果很有用,但在生产中通常为了安全而避免使用。
package com.zetcode;
import java.security.SecureRandom;
public class SecureRandomSeed {
public static void main(String[] args) {
SecureRandom secureRandom1 = new SecureRandom();
SecureRandom secureRandom2 = new SecureRandom();
// Set the same seed for both instances
byte[] seed = new byte[]{1, 2, 3, 4};
secureRandom1.setSeed(seed);
secureRandom2.setSeed(seed);
// Generate random integers
System.out.println("First SecureRandom int: " + secureRandom1.nextInt());
System.out.println("Second SecureRandom int: " + secureRandom2.nextInt());
}
}
我们为两个 SecureRandom 实例设置相同的种子,产生一致的结果。 在实践中,手动播种很少见,以保持不可预测性。
这对于调试或测试密码系统很有用,但在生产中应避免使用,以确保最大的随机性和安全性。
生成安全随机密钥
此示例演示了如何使用 SecureRandom 生成密码学密钥,这是安全通信协议中的常见要求。
package com.zetcode;
import java.security.SecureRandom;
import java.util.Base64;
public class SecureRandomKey {
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
// Generate a 256-bit (32-byte) key
byte[] key = new byte[32];
secureRandom.nextBytes(key);
// Encode to Base64 for readable output
String base64Key = Base64.getEncoder().encodeToString(key);
System.out.println("Secure 256-bit key (Base64): " + base64Key);
// Generate a 128-bit (16-byte) key
byte[] shortKey = new byte[16];
secureRandom.nextBytes(shortKey);
System.out.print("Secure 128-bit key (hex): ");
for (byte b : shortKey) {
System.out.printf("%02x", b);
}
System.out.println();
}
}
该程序生成适用于密码学密钥的安全字节数组,输出采用 Base64 和十六进制格式,以提高清晰度和可用性。
此类密钥对于 AES 等加密算法至关重要,可确保安全敏感应用程序中的安全数据传输或存储。
性能注意事项
此示例比较了 SecureRandom 和 Random 的性能,突出了随机数生成中安全性和速度之间的权衡。
package com.zetcode;
import java.security.SecureRandom;
import java.util.Random;
public class SecureRandomPerformance {
static final int COUNT = 1000000;
public static void main(String[] args) {
// Test Random
long start = System.currentTimeMillis();
Random random = new Random();
for (int i = 0; i < COUNT; i++) {
random.nextInt();
}
long duration = System.currentTimeMillis() - start;
System.out.println("Random time: " + duration + "ms");
// Test SecureRandom
start = System.currentTimeMillis();
SecureRandom secureRandom = new SecureRandom();
for (int i = 0; i < COUNT; i++) {
secureRandom.nextInt();
}
duration = System.currentTimeMillis() - start;
System.out.println("SecureRandom time: " + duration + "ms");
}
}
我们测量了使用两个类生成随机整数所花费的时间。 由于其密码学强度,SecureRandom 速度较慢,但对于安全性而言是必要的。
仅当需要密码学安全性时才使用 SecureRandom,因为对于非敏感任务,Random 或 ThreadLocalRandom 速度更快。
来源
本教程全面探讨了 Java SecureRandom 类,涵盖了基本用法、范围生成、安全字符串和密码学密钥。 这对于安全应用程序至关重要。
作者
列出所有Java教程。