javaWeb中使用AES256+RSA网络数据加密

AES256+RSA网络数据加密

为什么这么搭配?

  • AES:加密速度快,适合大数据量业务报文
  • RSA/ECC:只用来传 AES 密钥,不适合加密大文本
    说明:

Java 网络传输通用加解密工具类(AES+RSA 混合加密)

方案说明

AES:AES-128-CBC 加密业务报文(速度快、适合网络传输)

RSA:RSA-2048 加密 AES 随机密钥

流程:

  1. 客户端生成随机 AES 密钥 + 偏移量 IV
  2. AES 加密业务明文
  3. RSA 用服务端公钥加密 AES 密钥 + IV
  4. 传给后端:RSA 密文 + AES 业务密文
  5. 后端用私钥RSA 解密出 AES 密钥和 IV,再 AES 解业务数据

依赖(无需额外引入,JDK 原生)

JDK8+ 自带,不用导任何第三方包,直接能用。

java 复制代码
package com.pansoft.lcdp.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * 网络传输 AES+RSA 混合加解密工具
 * 适用:前后端接口、微服务敏感数据传输
 */
public class NetEncryptUtil {

    // ==================== AES 常量 ====================
    private static final String AES_ALGORITHM = "AES";
    private static final String AES_CIPHER_MODE = "AES/CBC/PKCS5Padding";
    // AES 128位 密钥长度
    private static final int AES_KEY_SIZE = 16;
    // CBC 模式偏移量 IV 长度
    private static final int AES_IV_SIZE = 16;

    // ==================== RSA 常量 ====================
    private static final String RSA_ALGORITHM = "RSA";
    private static final int RSA_KEY_SIZE = 2048;


    // ------------------------------ 生成RSA公私钥对 ------------------------------
    /**
     * 生成RSA 公钥、私钥 Base64 字符串
     */
    public static KeyPair generateRsaKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        keyPairGenerator.initialize(RSA_KEY_SIZE);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 公钥转Base64
     */
    public static String getPublicKeyBase64(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    /**
     * 私钥转Base64
     */
    public static String getPrivateKeyBase64(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }


    // ------------------------------ RSA 加解密 ------------------------------
    /**
     * RSA 公钥加密
     */
    public static String rsaEncrypt(String data, String publicKeyBase64) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyBase64);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PublicKey publicKey = keyFactory.generatePublic(spec);

        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptBytes);
    }

    /**
     * RSA 私钥解密
     */
    public static String rsaDecrypt(String encryptData, String privateKeyBase64) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(privateKeyBase64);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PrivateKey privateKey = keyFactory.generatePrivate(spec);

        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(encryptData));
        return new String(decryptBytes, StandardCharsets.UTF_8);
    }


    // ------------------------------ AES 随机生成密钥和IV ------------------------------
    /**
     * 生成随机16位AES密钥
     */
    public static String generateAesKey() {
        return getRandomStr(AES_KEY_SIZE);
    }

    /**
     * 生成随机16位IV
     */
    public static String generateAesIv() {
        return getRandomStr(AES_IV_SIZE);
    }

    /**
     * 生成指定长度随机字符串
     */
    private static String getRandomStr(int length) {
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder();
        SecureRandom random = new SecureRandom();
        for (int i = 0; i < length; i++) {
            int idx = random.nextInt(chars.length());
            sb.append(chars.charAt(idx));
        }
        return sb.toString();
    }


    // ------------------------------ AES 加解密 ------------------------------
    /**
     * AES CBC 加密
     */
    public static String aesEncrypt(String content, String aesKey, String iv) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        Cipher cipher = Cipher.getInstance(AES_CIPHER_MODE);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encryptBytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptBytes);
    }

    /**
     * AES CBC 解密
     */
    public static String aesDecrypt(String encryptContent, String aesKey, String iv) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), AES_ALGORITHM);
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        Cipher cipher = Cipher.getInstance(AES_CIPHER_MODE);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decryptBytes = cipher.doFinal(Base64.getDecoder().decode(encryptContent));
        return new String(decryptBytes, StandardCharsets.UTF_8);
    }


    // ------------------------------ 测试入口 ------------------------------
    public static void main(String[] args) throws Exception {
        // 1. 生成RSA公私钥对(服务端保存私钥,客户端下发公钥)
        KeyPair keyPair = generateRsaKeyPair();
        String pubKey = getPublicKeyBase64(keyPair.getPublic());
        String priKey = getPrivateKeyBase64(keyPair.getPrivate());
        System.out.println("RSA公钥:" + pubKey);
        System.out.println("RSA私钥:" + priKey);

        // 2. 客户端:生成随机AES密钥、IV
        String aesKey = generateAesKey();
        String aesIv = generateAesIv();
        String secret = aesKey + "|" + aesIv;

        // 3. 业务明文
        String plainText = "userId=10086&phone=13800138000&idCard=310101199001011234";

        // 4. AES加密业务数据
        String aesEncryptStr = aesEncrypt(plainText, aesKey, aesIv);
        // 5. RSA加密AES密钥+IV
        String rsaEncryptStr = rsaEncrypt(secret, pubKey);

        System.out.println("\nAES业务密文:" + aesEncryptStr);
        System.out.println("RSA密钥密文:" + rsaEncryptStr);


        // ========== 服务端解密流程 ==========
        // 1. RSA私钥解密 拿到AESKey和IV
        String decryptSecret = rsaDecrypt(rsaEncryptStr, priKey);
        String[] split = decryptSecret.split("\\|");
        String realAesKey = split[0];
        String realAesIv = split[1];

        // 2. AES解密业务数据
        String realPlain = aesDecrypt(aesEncryptStr, realAesKey, realAesIv);
        System.out.println("\n解密原文:" + realPlain);
    }
}
相关推荐
ch.ju1 小时前
Java Programming Chapter 3——If the array is out of range
java·开发语言
key_3_feng1 小时前
TCPDump 实际抓包案例及故障分析
网络·测试工具·tcpdump
康小汪1 小时前
IntelliJ IDEA 安装教程(Windows 版)
java·windows·intellij-idea
@SmartSi1 小时前
AgentScope Java 入门系列:Spring AI Alibaba 与 AgentScope 的定位与区别
java·spring·agentscope
一只大袋鼠1 小时前
JavaWeb四种文件上传方式(上篇)
java·开发语言·servlet·javaweb
网络工程小王1 小时前
【LangGraph的工作流编排能力】学习笔记
java·服务器·数据库·人工智能·langchain
她说可以呀1 小时前
JWT令牌检验用户是否登录
java·spring boot·spring·java-ee·maven
jimy11 小时前
Oracle的e2.1.micro免费实例安装tailscale后,设置为出口节点(Exit Node)
服务器·网络·oracle