AES与RSA联合使用进行加解密(C#、Java实现)

本文介绍如何结合使用AES和RSA加密算法来提高信息安全。通过AES加密大量数据并利用RSA加密AES密钥,确保了数据传输的安全性和高效性。

一、AES与RSA联合加密

1. 应用步骤:

  • AES(对称加密)与RSA(非对称加密)联合使用示例及步骤(A请求B的某个页面):
  1.  A端生成AES密钥
  2.  B端生成RSA公钥(用于加密)和私钥(用于解密),并将公钥给A
  3. A使用自己的AES密钥对自己的私密信息进行加密,并使用B提供的公钥对AES密钥进行加密,然后将请求信息和加密后的AES密钥发送给B
  4. B使用RSA私钥对加密的AES密钥进行解密,然后用AES密钥对A的请求信息进行解密
  5. B验证A的请求信息,实现后续的操作。

2. 理论基础

  • 为什么联合使用AES与RSA加密算法
  1. AES是对称加密算法,在传输过程中容易被窃取,但加密效率高
  2. RSA是非对称加密算法,安全性高,但加密效率低
  3. RSA公钥加密的内容,只有对应的私钥才能解密,对于较长的内容,可以选择使用AES加密,然后用公钥加密AES密钥的方式进行加密。

二、代码实现秘钥生成以及加密解密操作

1. C# 实现

1.1 AES生成密钥、AES加解密操作

public class AESUtil
{
    //生成AES密钥
    public static Aes GenerateAES()
    {
        Aes aes=Aes.Create();
        return aes;
    }
    //获取AES密钥
    public static byte[] GetAESKey(Aes aes)
    {
        byte[] key = aes.Key;
        return key;
    }
    //使用AES加密数据
    public static string AESEncript(string data, byte[] aesKey)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = aesKey;
            aes.IV = new byte[16];
            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key,aes.IV);
            using (MemoryStream ms=new MemoryStream())
            {
                using (CryptoStream cs=new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter sw=new StreamWriter(cs))
                    {
                        sw.Write(data);
                    }
                }
                return Convert.ToBase64String(ms.ToArray());
            }
        }
    }
    //使用AES解密数据
    public static string AESDecript(string data,byte[] aesKey)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = aesKey;
            aes.IV=new byte[16];
            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key,aes.IV);
            using (MemoryStream ms =new MemoryStream(Convert.FromBase64String(data)))
            {
                using (CryptoStream cs=new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader sr=new StreamReader(cs))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
        }
    }
}

  1.2 RSA密钥生成、RSA加解密

public class RSAUtil
{
    //生成RSA密钥对
    public static RSA GenerateRSA()
    {
        RSA rsa=RSA.Create(2048);
        return rsa;
    }
    //获取公钥
    public static byte[] GetRSAPublicKey(RSA rsa)
    {
        var publicKey = rsa.ExportRSAPublicKey();  //导出当前密钥的公钥部分
        return publicKey;
    }
    //获取私钥
    public static byte[] GetRSAPrivateKey(RSA rsaKeyPair)
    {
        var privateKey = rsaKeyPair.ExportRSAPrivateKey();//导出当前密钥的私钥部分
        return privateKey;
    }
    //公钥加密
    public static byte[] RSAEncrypt(byte[] data,byte[] publicKey)
    {
        using (RSA rsa = RSA.Create())
        {
            rsa.ImportRSAPublicKey(publicKey,out int bytesRead);//导入公钥,从 PKCS#1 RSAPublicKey 结构中导入公钥
            return rsa.Encrypt(data,RSAEncryptionPadding.Pkcs1);//加密,RSAEncryptionPadding.Pkcs1:加密标准
        }
    }
    //私钥解密
    public static byte[] RSADecrypt(byte[] data, byte[] privateKey)
    {
        using (RSA rsa = RSA.Create())
        {
            rsa.ImportRSAPrivateKey(privateKey,out int bytesRead);
            return rsa.Decrypt(data, RSAEncryptionPadding.Pkcs1);
        }
    }
}
        扩展:从.pem文件中读取秘钥进行信息加密:
public string GetRSAToEncrypt()
{
    string file_path = "D:/public_key.pem";
    using (StreamReader reader = new StreamReader(file_path))
    {
        var pem = reader.BaseStream;
        byte[] buffer = new byte[pem.Length];
        pem.Read(buffer, 0, buffer.Length);
        var content = Encoding.UTF8.GetBytes("aaa");
        string result = "";
        using (RSA rsa = RSA.Create())
        {
            rsa.ImportSubjectPublicKeyInfo(buffer, out int bt);
            var en = rsa.Encrypt(content, RSAEncryptionPadding.Pkcs1);
            result = Convert.ToBase64String(en);
        }
        return result;
    }
}

 1.3 AES与RSA联合使用实现加解密步骤:

//生成AES密钥
Aes aes = AESUtil.GenerateAES();
byte[] aesKey = AESUtil.GetAESKey(aes);
//用AES密钥对信息加密
string enCryptInfo = AESUtil.AESEncript(userInfo, aesKey);
//用公钥对AES密钥加密(若是对string类型加密,加密前要先Encoding.UTF8.GetBytes(content))
byte[] enCryptAESByRSA = RSAUtil.RSAEncrypt(aesKey, rsaPublicKey);
//用私钥对加密的AES解密
byte[] deCryptAESByRSA = RSAUtil.RSADecrypt(enCryptAESByRSA, rsaPrivateKey);
//用AES对加密信息解密
string deCryptInfo = AESUtil.AESDecript(enCryptInfo, deCryptAESByRSA);

2. Java实现

2.0 添加依赖

<!-- hutool 工具包-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>${hutool.version}</version>
</dependency>

 2.1 RSA秘钥对生成

生成RSA秘钥对,并将生成的秘钥保存为.pem文件

import cn.hutool.crypto.asymmetric.RSA;
@Service
public class RsaUtils {
    public Object getRsaKeys()
    {
        //生成秘钥对
        RSA rsa=new RSA();
        String publicKey=rsa.getPublicKeyBase64();
        String privateKey=rsa.getPrivateKeyBase64();

        Map<String,String> rsaKeys= new HashMap<String,String>();
        rsaKeys.put("public_key",publicKey);
        rsaKeys.put("private_key",privateKey);

        //转换为pem文件的保存格式
        String publicKey_pem=formatKeyToPem("PUBLIC KEY",publicKey);
        String privateKey_pem=formatKeyToPem("PRIVATE KEY",privateKey);

        //保存为pem文件
        String path= Paths.get("").toAbsolutePath()+"/Files/Keys/";
        try(PrintWriter pw=new PrintWriter(new FileWriter(path+"rsa_pubilcKey.pem")))
        {
            pw.println(publicKey_pem);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try(PrintWriter pw=new PrintWriter(new FileWriter(path+"rsa_privateKey.pem")))
        {
            pw.println(privateKey_pem);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return rsaKeys;
    }
    private String formatKeyToPem(String keyType,String base64Key)
    {
        final int line_length=64;
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("-----BEGIN ")
                .append(keyType)
                .append("-----\n");
        for(int i=0;i<base64Key.length();i+=line_length)
        {
            int endIndex=Math.min(i+line_length,base64Key.length());
            stringBuilder.append(base64Key,i,endIndex).append("\n");
        }
        stringBuilder.append("-----END ")
                .append(keyType)
                .append("-----\n");
        return stringBuilder.toString();
    }
}

2.2 RSA加密与解密

//加密
public String RsaEncrypt(String data)
{
    try{
        //获取公钥
        String public_key=getRsaKey("rsa_pubilcKey.pem");
        //创建RSA实例,使用公钥进行加密
        RSA rsa=new RSA(null,public_key);
        byte[] dataEncrypted=rsa.encrypt(data.getBytes(StandardCharsets.UTF_8), KeyType.PublicKey);
        //加密内容格式化
        String dataBase64= Base64Encoder.encode(dataEncrypted);//转化为Base64编码
        String dateUrlEncode=URLEncoder.encode(dataBase64,"UTF-8");//将字符串处理成适合在url中传输的格式
        return dateUrlEncode;
    }
    catch (Exception ex)
    {
        return ex.getMessage();
    }
}
//解密
public String RsaDecrypt(String encryptedData)
{
    try{
        //获取私钥
        String privateKey=getRsaKey("rsa_privateKey.pem");

        //加密信息处理
        String base64Data= URLDecoder.decode(encryptedData,"UTF-8");
        byte[] byteData= Base64Decoder.decode(base64Data);

        //创建RSA实例,使用RSA私钥进行解密
        RSA rsa=new RSA(privateKey,null);
        byte[] decryptedData=rsa.decrypt(byteData,KeyType.PrivateKey);

        String result=new String(decryptedData);
        return result;
    }
    catch (Exception ex)
    {
        return ex.getMessage();
    }
}
//获取秘钥
private String getRsaKey(String fileName)
{
    String path=Paths.get("").toAbsolutePath()+"/Files/Keys/"+fileName;
    try{
        String rsaKey=new String(Files.readAllBytes(Paths.get(path)));
        rsaKey=rsaKey.replace("-----BEGIN PRIVATE KEY-----","")
                .replace("-----END PRIVATE KEY-----","")
                .replace("-----BEGIN PUBLIC KEY-----","")
                .replace("-----END PUBLIC KEY-----","")
                .replaceAll("\\s+","");//取出所有的空格、回车、tab键
        return rsaKey;
    }
    catch (Exception ex)
    {
        return ex.getMessage();
    }
}

 2.3 AES秘钥生成

 2.3.0 所用依赖

两种用于AES加密的依赖:

  • KeyGenerator

    • 允许自定义密钥长度(128、192、256位等)。
    • 适用于标准的Java加密架构。
    • 提供更细致的控制,适合需要特定配置的场景。
    • 只适用于对称加密算法,如AES、DES等。
  • Hutool的AES类

    • 更简洁,快速生成AES密钥,适合快速开发。
    • 默认生成密钥,配置较少。
    • 适合日常使用,不需要过多配置
2.3.1 使用Hutool的AES类生成秘钥
import cn.hutool.crypto.symmetric.AES;
@Service
public class AESUtils {
    public String getAesKey()
    {
        AES aes=new AES();
        byte[] aesKey=aes.getSecretKey().getEncoded();
        String key= Base64Encoder.encode(aesKey);
        String path= Paths.get("").toAbsolutePath()+"/Files/Keys/aes_key.txt";
        try(PrintWriter pw=new PrintWriter(new FileWriter(path)))
        {
            pw.println(key);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return key;
    }
}
 2.3.2 使用KeyGenerator生成秘钥
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public String getFixedLengthAesKey(int length)
{
    try {
        //创建KeyGenerator对象,指定AES算法
        KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
        //初始化秘钥大小,常见128,192,256
        keyGenerator.init(length);
        //生成AES秘钥
        SecretKey secretKey=keyGenerator.generateKey();
        byte[] keyByte=secretKey.getEncoded();
        String keyBase64=Base64Encoder.encode(keyByte);
        return keyBase64;
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }

}

 未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值