SecureRandom案例

wen java案例 1

本文目录导读:

SecureRandom案例

  1. 基础使用 - 生成随机数
  2. 生成随机密码
  3. 生成随机令牌/会话ID
  4. 文件加密密钥生成
  5. 线程安全的SecureRandom单例
  6. 防碰撞的唯一ID生成器
  7. 关键要点

我为您提供几个Java中使用SecureRandom的实用案例,涵盖不同场景。

基础使用 - 生成随机数

import java.security.SecureRandom;
public class BasicSecureRandom {
    public static void main(String[] args) {
        // 创建SecureRandom实例
        SecureRandom secureRandom = new SecureRandom();
        // 生成随机整数
        int randomInt = secureRandom.nextInt();
        System.out.println("随机整数: " + randomInt);
        // 生成0-99的随机数
        int randomRange = secureRandom.nextInt(100);
        System.out.println("0-99的随机数: " + randomRange);
        // 生成随机长整数
        long randomLong = secureRandom.nextLong();
        System.out.println("随机长整数: " + randomLong);
        // 生成随机布尔值
        boolean randomBoolean = secureRandom.nextBoolean();
        System.out.println("随机布尔值: " + randomBoolean);
        // 生成随机浮点数 (0.0 - 1.0)
        float randomFloat = secureRandom.nextFloat();
        System.out.println("随机浮点数: " + randomFloat);
        // 生成随机双精度浮点数 (0.0 - 1.0)
        double randomDouble = secureRandom.nextDouble();
        System.out.println("随机双精度浮点数: " + randomDouble);
    }
}

生成随机密码

import java.security.SecureRandom;
public class RandomPasswordGenerator {
    private static final String CHAR_LOWER = "abcdefghijklmnopqrstuvwxyz";
    private static final String CHAR_UPPER = CHAR_LOWER.toUpperCase();
    private static final String NUMBER = "0123456789";
    private static final String OTHER_CHAR = "!@#$%^&*()-_=+[]{};:,.?";
    private static final String PASSWORD_ALLOW_BASE = CHAR_LOWER + CHAR_UPPER + NUMBER + OTHER_CHAR;
    private static final SecureRandom RANDOM = new SecureRandom();
    public static String generateRandomPassword(int length) {
        if (length < 4) {
            throw new IllegalArgumentException("密码长度至少为4位");
        }
        StringBuilder sb = new StringBuilder(length);
        // 确保密码包含至少一种字符类型
        sb.append(getRandomChar(CHAR_LOWER));
        sb.append(getRandomChar(CHAR_UPPER));
        sb.append(getRandomChar(NUMBER));
        sb.append(getRandomChar(OTHER_CHAR));
        // 填充剩余长度
        for (int i = 4; i < length; i++) {
            sb.append(getRandomChar(PASSWORD_ALLOW_BASE));
        }
        // 使用Fisher-Yates算法打乱顺序
        String password = sb.toString();
        char[] passwordArray = password.toCharArray();
        for (int i = passwordArray.length - 1; i > 0; i--) {
            int j = RANDOM.nextInt(i + 1);
            char temp = passwordArray[i];
            passwordArray[i] = passwordArray[j];
            passwordArray[j] = temp;
        }
        return new String(passwordArray);
    }
    private static char getRandomChar(String source) {
        int index = RANDOM.nextInt(source.length());
        return source.charAt(index);
    }
    public static void main(String[] args) {
        // 生成10个不同的16位密码
        for (int i = 0; i < 10; i++) {
            System.out.println("密码 " + (i + 1) + ": " + generateRandomPassword(16));
        }
    }
}

生成随机令牌/会话ID

import java.security.SecureRandom;
import java.util.Base64;
public class TokenGenerator {
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    // 生成Base64编码的随机令牌
    public static String generateBase64Token(int byteLength) {
        byte[] bytes = new byte[byteLength];
        SECURE_RANDOM.nextBytes(bytes);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
    }
    // 生成十六进制随机令牌
    public static String generateHexToken(int byteLength) {
        byte[] bytes = new byte[byteLength];
        SECURE_RANDOM.nextBytes(bytes);
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    // 生成数字一次性密码 (OTP)
    public static String generateOTP(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(SECURE_RANDOM.nextInt(10));
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        System.out.println("Base64 Token (32 bytes): " + generateBase64Token(32));
        System.out.println("Hex Token (16 bytes): " + generateHexToken(16));
        System.out.println("6位OTP: " + generateOTP(6));
        System.out.println("8位OTP: " + generateOTP(8));
    }
}

文件加密密钥生成

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class EncryptionKeyGenerator {
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    // 使用SecureRandom生成AES密钥
    public static SecretKey generateAESKey(int keySize) throws NoSuchAlgorithmException {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(keySize, SECURE_RANDOM);
        return keyGen.generateKey();
    }
    // 使用SecureRandom生成随机密钥(任意算法)
    public static byte[] generateRandomKey(int keySize) {
        byte[] key = new byte[keySize / 8];
        SECURE_RANDOM.nextBytes(key);
        return key;
    }
    // 生成AES密钥并转换为Base64字符串
    public static String generateAESKeyBase64(int keySize) throws NoSuchAlgorithmException {
        SecretKey key = generateAESKey(keySize);
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }
    public static void main(String[] args) {
        try {
            // 生成128位AES密钥
            System.out.println("AES-128密钥 (Base64): " + generateAESKeyBase64(128));
            // 生成256位AES密钥
            System.out.println("AES-256密钥 (Base64): " + generateAESKeyBase64(256));
            // 生成32字节随机密钥(256位)
            byte[] keyBytes = generateRandomKey(256);
            System.out.println("Hmac密钥 (Hex): " + bytesToHex(keyBytes));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

线程安全的SecureRandom单例

import java.security.SecureRandom;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadSafeSecureRandom {
    // 使用ThreadLocal确保每个线程有自己的SecureRandom实例
    private static final ThreadLocal<SecureRandom> THREAD_LOCAL = 
        ThreadLocal.withInitial(SecureRandom::new);
    // 或者使用静态实例(SecureRandom本身是线程安全的)
    private static final SecureRandom SHARED_RANDOM = new SecureRandom();
    public static int getRandomInt(int bound) {
        // 使用ThreadLocal版本
        return THREAD_LOCAL.get().nextInt(bound);
    }
    public static String getRandomToken(int bytes) {
        // 使用共享实例
        byte[] token = new byte[bytes];
        SHARED_RANDOM.nextBytes(token);
        return bytesToHex(token);
    }
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            final int taskId = i;
            executor.submit(() -> {
                int random = getRandomInt(1000);
                String token = getRandomToken(16);
                System.out.println("任务 " + taskId + " - 随机数: " + random + ", Token: " + token);
            });
        }
        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);
    }
}

防碰撞的唯一ID生成器

import java.security.SecureRandom;
import java.time.Instant;
public class SecureIdGenerator {
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    /**
     * 生成UUID (版本4)
     */
    public static String generateUUID() {
        byte[] randomBytes = new byte[16];
        SECURE_RANDOM.nextBytes(randomBytes);
        // 设置版本为4
        randomBytes[6] &= 0x0f;
        randomBytes[6] |= 0x40;
        // 设置变体
        randomBytes[8] &= 0x3f;
        randomBytes[8] |= 0x80;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < randomBytes.length; i++) {
            if (i == 4 || i == 6 || i == 8 || i == 10) {
                sb.append('-');
            }
            sb.append(String.format("%02x", randomBytes[i]));
        }
        return sb.toString();
    }
    /**
     * 生成带时间戳的唯一ID
     */
    public static String generateTimestampId() {
        long timestamp = Instant.now().toEpochMilli();
        byte[] randomBytes = new byte[8];
        SECURE_RANDOM.nextBytes(randomBytes);
        return String.format("%d-%s", timestamp, bytesToHex(randomBytes));
    }
    /**
     * 生成雪花算法风格的ID
     */
    public static long generateSnowflakeId() {
        long timestamp = System.currentTimeMillis() << 22;
        long randomPart = (long)(SECURE_RANDOM.nextDouble() * (1 << 22));
        return timestamp + randomPart;
    }
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        System.out.println("UUID v4: " + generateUUID());
        System.out.println("时间戳ID: " + generateTimestampId());
        // 生成多个ID验证唯一性
        for (int i = 0; i < 5; i++) {
            System.out.println("雪花ID " + (i + 1) + ": " + generateSnowflakeId());
        }
    }
}

关键要点

  1. 安全性SecureRandom基于密码学安全算法,适合安全敏感场景
  2. 线程安全SecureRandom实例是线程安全的,可以共享使用
  3. 性能:首次初始化可能较慢,但后续操作性能良好
  4. 选择建议
    • 一般场景:new SecureRandom()
    • 高性能系统:使用ThreadLocal<SecureRandom>
    • 安全关键用途:考虑显式指定算法(如SHA1PRNGNativePRNG

这些案例覆盖了大多数实际应用场景,您可以根据具体需求选择适合的实现。

抱歉,评论功能暂时关闭!