Java案例如何实现非对称加密?

wen java案例 76

本文目录导读:

Java案例如何实现非对称加密?

  1. RSA非对称加密完整示例
  2. 高级应用:混合加密系统
  3. 文件加密示例
  4. 性能对比和最佳实践
  5. 安全注意事项

我来详细介绍Java中实现非对称加密的完整案例。

RSA非对称加密完整示例

核心工具类

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAEncryptionUtil {
    // 生成密钥对
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(2048); // 密钥长度:1024/2048/4096
        return generator.generateKeyPair();
    }
    // 公钥加密
    public static String encrypt(String plainText, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    // 私钥解密
    public static String decrypt(String encryptedText, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
        return new String(decryptedBytes, "UTF-8");
    }
    // 私钥签名
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes("UTF-8"));
        byte[] signBytes = signature.sign();
        return Base64.getEncoder().encodeToString(signBytes);
    }
    // 公钥验签
    public static boolean verify(String data, String signatureStr, PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(data.getBytes("UTF-8"));
        return signature.verify(Base64.getDecoder().decode(signatureStr));
    }
    // 密钥转字符串
    public static String keyToString(Key key) {
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }
    // 字符串转公钥
    public static PublicKey stringToPublicKey(String keyStr) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(keyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }
    // 字符串转私钥
    public static PrivateKey stringToPrivateKey(String keyStr) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(keyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }
}

测试示例

public class RSAEncryptionDemo {
    public static void main(String[] args) {
        try {
            System.out.println("=== RSA非对称加密示例 ===");
            // 1. 生成密钥对
            KeyPair keyPair = RSAEncryptionUtil.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            System.out.println("公钥: " + RSAEncryptionUtil.keyToString(publicKey));
            System.out.println("私钥: " + RSAEncryptionUtil.keyToString(privateKey));
            // 2. 加解密测试
            String originalData = "Hello, 这是需要加密的敏感数据!";
            System.out.println("\n原始数据: " + originalData);
            // 公钥加密
            String encryptedData = RSAEncryptionUtil.encrypt(originalData, publicKey);
            System.out.println("加密后: " + encryptedData);
            // 私钥解密
            String decryptedData = RSAEncryptionUtil.decrypt(encryptedData, privateKey);
            System.out.println("解密后: " + decryptedData);
            // 3. 签名验证测试
            String signData = "需要签名的数据";
            String signature = RSAEncryptionUtil.sign(signData, privateKey);
            System.out.println("\n签名: " + signature);
            boolean isValid = RSAEncryptionUtil.verify(signData, signature, publicKey);
            System.out.println("签名验证结果: " + isValid);
            // 4. 密钥持久化示例
            System.out.println("\n=== 密钥持久化示例 ===");
            // 保存密钥
            String savedPublicKey = RSAEncryptionUtil.keyToString(publicKey);
            String savedPrivateKey = RSAEncryptionUtil.keyToString(privateKey);
            // 从字符串恢复密钥
            PublicKey loadedPublicKey = RSAEncryptionUtil.stringToPublicKey(savedPublicKey);
            PrivateKey loadedPrivateKey = RSAEncryptionUtil.stringToPrivateKey(savedPrivateKey);
            // 验证恢复后的密钥可用
            String testData = "测试持久化密钥";
            String encrypted = RSAEncryptionUtil.encrypt(testData, loadedPublicKey);
            String decrypted = RSAEncryptionUtil.decrypt(encrypted, loadedPrivateKey);
            System.out.println("密钥持久化测试: " + testData.equals(decrypted));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

高级应用:混合加密系统

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.util.Base64;
/**
 * 混合加密系统:RSA + AES
 * 解决RSA加密大数据的性能问题
 */
public class HybridEncryptionSystem {
    private RSAEncryptionUtil rsaUtil;
    public HybridEncryptionSystem() {
        this.rsaUtil = new RSAEncryptionUtil();
    }
    /**
     * 混合加密:AES加密数据,RSA加密AES密钥
     */
    public static class EncryptedData {
        private String encryptedKey;    // RSA加密的AES密钥
        private String encryptedData;   // AES加密的数据
        public EncryptedData(String encryptedKey, String encryptedData) {
            this.encryptedKey = encryptedKey;
            this.encryptedData = encryptedData;
        }
        public String getEncryptedKey() {
            return encryptedKey;
        }
        public String getEncryptedData() {
            return encryptedData;
        }
    }
    /**
     * 混合加密
     */
    public EncryptedData hybridEncrypt(String data, PublicKey publicKey) throws Exception {
        // 1. 生成AES密钥
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(256);  // AES-256
        SecretKey aesKey = keyGen.generateKey();
        // 2. AES加密数据
        Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
        byte[] encryptedData = aesCipher.doFinal(data.getBytes("UTF-8"));
        // 3. RSA加密AES密钥
        String encryptedKey = rsaUtil.encrypt(
            Base64.getEncoder().encodeToString(aesKey.getEncoded()), 
            publicKey
        );
        return new EncryptedData(
            encryptedKey,
            Base64.getEncoder().encodeToString(encryptedData)
        );
    }
    /**
     * 混合解密
     */
    public String hybridDecrypt(EncryptedData encryptedData, PrivateKey privateKey) throws Exception {
        // 1. RSA解密获取AES密钥
        String aesKeyStr = rsaUtil.decrypt(encryptedData.getEncryptedKey(), privateKey);
        byte[] aesKeyBytes = Base64.getDecoder().decode(aesKeyStr);
        SecretKey aesKey = new SecretKeySpec(aesKeyBytes, "AES");
        // 2. AES解密数据
        Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        aesCipher.init(Cipher.DECRYPT_MODE, aesKey);
        byte[] decryptedData = aesCipher.doFinal(
            Base64.getDecoder().decode(encryptedData.getEncryptedData())
        );
        return new String(decryptedData, "UTF-8");
    }
}
// 混合加密测试
class HybridEncryptionDemo {
    public static void main(String[] args) throws Exception {
        System.out.println("=== 混合加密系统示例 ===");
        // 生成RSA密钥对
        KeyPair keyPair = RSAEncryptionUtil.generateKeyPair();
        HybridEncryptionSystem hybridSystem = new HybridEncryptionSystem();
        // 大数据测试
        StringBuilder largeData = new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            largeData.append("这是一段很长的测试数据,需要混合加密系统来处理。");
        }
        String originalData = largeData.toString();
        System.out.println("原始数据长度: " + originalData.length() + " 字符");
        // 混合加密
        long startTime = System.currentTimeMillis();
        HybridEncryptionSystem.EncryptedData encrypted = 
            hybridSystem.hybridEncrypt(originalData, keyPair.getPublic());
        long encryptTime = System.currentTimeMillis() - startTime;
        System.out.println("加密耗时: " + encryptTime + "ms");
        System.out.println("加密后密钥长度: " + encrypted.getEncryptedKey().length());
        System.out.println("加密后数据长度: " + encrypted.getEncryptedData().length());
        // 混合解密
        startTime = System.currentTimeMillis();
        String decryptedData = hybridSystem.hybridDecrypt(encrypted, keyPair.getPrivate());
        long decryptTime = System.currentTimeMillis() - startTime;
        System.out.println("解密耗时: " + decryptTime + "ms");
        System.out.println("解密后数据长度: " + decryptedData.length());
        System.out.println("加解密验证: " + originalData.equals(decryptedData));
    }
}

文件加密示例

import java.io.*;
import java.nio.file.*;
import java.security.*;
public class FileEncryptionUtil {
    /**
     * 加密文件
     */
    public static void encryptFile(String sourceFile, String destFile, 
                                    PublicKey publicKey) throws Exception {
        byte[] fileData = Files.readAllBytes(Paths.get(sourceFile));
        String encryptedData = RSAEncryptionUtil.encrypt(
            Base64.getEncoder().encodeToString(fileData), 
            publicKey
        );
        Files.write(Paths.get(destFile), encryptedData.getBytes("UTF-8"));
    }
    /**
     * 解密文件
     */
    public static void decryptFile(String sourceFile, String destFile, 
                                    PrivateKey privateKey) throws Exception {
        String encryptedData = new String(
            Files.readAllBytes(Paths.get(sourceFile)), "UTF-8"
        );
        String decryptedData = RSAEncryptionUtil.decrypt(encryptedData, privateKey);
        byte[] originalData = Base64.getDecoder().decode(decryptedData);
        Files.write(Paths.get(destFile), originalData);
    }
    public static void main(String[] args) throws Exception {
        // 生成密钥对
        KeyPair keyPair = RSAEncryptionUtil.generateKeyPair();
        // 创建测试文件
        Path testFile = Paths.get("test.txt");
        Files.write(testFile, "这是文件加密测试内容".getBytes("UTF-8"));
        // 加密文件
        encryptFile("test.txt", "test.encrypted", keyPair.getPublic());
        System.out.println("文件加密完成");
        // 解密文件
        decryptFile("test.encrypted", "test.decrypted.txt", keyPair.getPrivate());
        System.out.println("文件解密完成");
        // 验证
        String original = new String(Files.readAllBytes(testFile), "UTF-8");
        String decrypted = new String(Files.readAllBytes(Paths.get("test.decrypted.txt")), "UTF-8");
        System.out.println("文件加解密验证: " + original.equals(decrypted));
        // 清理测试文件
        Files.deleteIfExists(testFile);
        Files.deleteIfExists(Paths.get("test.encrypted"));
        Files.deleteIfExists(Paths.get("test.decrypted.txt"));
    }
}

性能对比和最佳实践

public class EncryptionBenchmark {
    public static void main(String[] args) throws Exception {
        KeyPair keyPair = RSAEncryptionUtil.generateKeyPair();
        System.out.println("=== 加密性能测试 ===");
        // 不同数据大小的加密耗时
        int[] dataSizes = {100, 1000, 10000};
        for (int size : dataSizes) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < size; i++) {
                sb.append("A");
            }
            String data = sb.toString();
            // RSA加密
            long startTime = System.nanoTime();
            String encrypted = RSAEncryptionUtil.encrypt(data, keyPair.getPublic());
            long rsaTime = System.nanoTime() - startTime;
            System.out.printf("RSA加密 %d 字节: %d μs%n", size, rsaTime / 1000);
        }
    }
}

安全注意事项

public class SecurityBestPractices {
    /**
     * 安全密钥管理示例
     */
    public static class KeyStoreManager {
        private static final String KEYSTORE_TYPE = "PKCS12";
        private static final String KEY_ALIAS = "mykey";
        /**
         * 保存密钥到KeyStore
         */
        public static void saveKeyToKeyStore(PrivateKey privateKey, 
                                              char[] password, 
                                              String keyStorePath) throws Exception {
            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
            keyStore.load(null, null);
            // 保存私钥
            KeyStore.PrivateKeyEntry privateKeyEntry = 
                new KeyStore.PrivateKeyEntry(privateKey, new java.security.cert.Certificate[0]);
            keyStore.setEntry(KEY_ALIAS, privateKeyEntry, 
                new KeyStore.PasswordProtection(password));
            // 保存到文件
            try (FileOutputStream fos = new FileOutputStream(keyStorePath)) {
                keyStore.store(fos, password);
            }
        }
        /**
         * 从KeyStore加载私钥
         */
        public static PrivateKey loadPrivateKey(char[] password, 
                                                 String keyStorePath) throws Exception {
            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
            try (FileInputStream fis = new FileInputStream(keyStorePath)) {
                keyStore.load(fis, password);
            }
            return (PrivateKey) keyStore.getKey(KEY_ALIAS, password);
        }
    }
}
  1. 密钥安全:私钥必须安全存储,推荐使用KeyStore
  2. 数据大小限制:RSA加密数据不能超过密钥长度(如2048位=245字节)
  3. 填充方式:PKCS1Padding是标准填充方式
  4. 性能优化:大数据使用混合加密(RSA+AES)
  5. 签名验证:用于数据完整性验证
  6. 密钥长度:建议至少2048位

这个完整的示例提供了从基础到高级的RSA加密实现,涵盖了实际开发中常见的应用场景。

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