前后端加密通信:RSA与AES(GCM模式)的结合应用

加密过程

1.1生成RSA密钥对

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;

public class RSAKeyPairGenerator {
    private KeyPair keyPair;

    public RSAKeyPairGenerator() throws NoSuchAlgorithmException {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        this.keyPair = keyGen.generateKeyPair();
    }

    public KeyPair getKeyPair() {
        return keyPair;
    }
}

2.加密AES密钥并发送给客户端

import javax.crypto.Cipher;
import java.security.PublicKey;

public class RSAEncrypt {
    public byte[] encryptAESKey(byte[] aesKey, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(aesKey);
    }
}

3.使用AES-GCM模式加密数据

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AESGCMEncrypt {
    private static final int AES_KEY_SIZE = 256;
    private static final int GCM_IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 16;

    public static SecretKey generateAESKey() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(AES_KEY_SIZE);
        return keyGen.generateKey();
    }

    public static byte[] encrypt(byte[] plaintext, SecretKey key, byte[] iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
        cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec);
        return cipher.doFinal(plaintext);
    }

    public static byte[] generateIV() {
        byte[] iv = new byte[GCM_IV_LENGTH];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        return iv;
    }
}

4.服务端逻辑整合

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.SecretKey;

public class Server {
    public static void main(String[] args) {
        try {
            // 生成RSA密钥对
            RSAKeyPairGenerator rsaKeyPairGenerator = new RSAKeyPairGenerator();
            KeyPair keyPair = rsaKeyPairGenerator.getKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            // 生成AES密钥
            SecretKey aesKey = AESGCMEncrypt.generateAESKey();

            // 加密AES密钥
            RSAEncrypt rsaEncrypt = new RSAEncrypt();
            byte[] encryptedAESKey = rsaEncrypt.encryptAESKey(aesKey.getEncoded(), publicKey);

            // 生成IV
            byte[] iv = AESGCMEncrypt.generateIV();

            // 加密数据(示例数据)
            String plaintext = "This is a secret message.";
            byte[] encryptedData = AESGCMEncrypt.encrypt(plaintext.getBytes(), aesKey, iv);

            // 输出加密结果
            System.out.println("Encrypted AES Key: " + Base64.getEncoder().encodeToString(encryptedAESKey));
            System.out.println("IV: " + Base64.getEncoder().encodeToString(iv));
            System.out.println("Encrypted Data: " + Base64.getEncoder().encodeToString(encryptedData));

            // 这里可以将加密的AES密钥、IV和加密的数据发送给客户端

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.解密过程

1.RSA解密AES密钥

import javax.crypto.Cipher;
import java.security.PrivateKey;

public class RSADecrypt {
    public byte[] decryptAESKey(byte[] encryptedAESKey, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(encryptedAESKey);
    }
}

2.使用AES-GCM解密数据

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESGCMDecrypt {
    private static final int GCM_TAG_LENGTH = 16;

    public static byte[] decrypt(byte[] ciphertext, SecretKey key, byte[] iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
        cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec);
        return cipher.doFinal(ciphertext);
    }
}

2.服务端解密逻辑整合

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class ServerDecrypt {
    public static void main(String[] args) {
        try {
            // 生成RSA密钥对(在实际应用中,这应该是从安全存储中加载的)
            RSAKeyPairGenerator rsaKeyPairGenerator = new RSAKeyPairGenerator();
            KeyPair keyPair = rsaKeyPairGenerator.getKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            // 假设这些数据是从客户端接收到的
            String encryptedAESKeyBase64 = "接收到的加密AES密钥的Base64字符串";
            String ivBase64 = "接收到的IV的Base64字符串";
            String encryptedDataBase64 = "接收到的加密数据的Base64字符串";

            // 将Base64字符串转换为字节数组
            byte[] encryptedAESKey = Base64.getDecoder().decode(encryptedAESKeyBase64);
            byte[] iv = Base64.getDecoder().decode(ivBase64);
            byte[] encryptedData = Base64.getDecoder().decode(encryptedDataBase64);

            // 解密AES密钥
            RSADecrypt rsaDecrypt = new RSADecrypt();
            byte[] aesKeyBytes = rsaDecrypt.decryptAESKey(encryptedAESKey, privateKey);
            SecretKey aesKey = new SecretKeySpec(aesKeyBytes, 0, aesKeyBytes.length, "AES");

            // 解密数据
            byte[] decryptedData = AESGCMDecrypt.decrypt(encryptedData, aesKey, iv);

            // 输出解密结果
            String plaintext = new String(decryptedData);
            System.out.println("Decrypted Data: " + plaintext);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意事项:

1.选择合适的密钥长度:RSA和AES的密钥长度对安全性有很大影响。一般来说,RSA密钥长度建议选择2048位或更高,AES密钥长度建议选择128位、192位或256位

2.iv长度一般是96位12个(字节);tag长度为128位(16个字节)

3.Cipher包生成的密文是带有tag的,而且也会校验tag;那也就意味着客户端传的密文也要带上tag,一般拼接在密文后

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值