JAVA-WEB项目中,前后台结合AES和RSA对数据加密处理

实际项目中为了系统安全,我们经常需要对请求数据和响应数据做加密处理,这里以spring后台,vue前台的java web为例,记录一个实现过程

一、为什么要结合AES和RSA?

因为AES是对称加密,即加密解密用的秘钥是一样,这样一来AES的秘钥保管尤其重要,但是AES有个很好的优点,就是处理效率高。而RSA是不对称加密,即加密解密用的秘钥不一样,分别叫公钥和私钥,通常用公钥加密,然后用私钥解密,其中公钥可以公开,只需要保管好私钥即可,而相比AES而言RSA速度慢效率低。所以,通常我们结合这两种加密方式的优点来完成数据的安全传输。

二、AES和RSA的结合使用过程

1.前端随机动态生成aesKey:因为AES的加密解密秘钥需要一致,如果整个系统写死AES的秘钥会很不安全,所以每次请求动态生成aesKey会比较好

2.前端用RSA对动态aesKey加密:动态aesKey需要传到后端供解密,传输过程用RSA加密

3.前端保存动态aesKey:因为同一个请求的响应需要一样的aesKey解密,所以前端还得把动态aesKey保存下来,可以再随机生成一个id,然后按键值对的方式保存在前端变量中{id: aesKey}

4.把加密的aesKey和id放到请求头

5.后端用RSA私钥解密得明文aesKey:后端从请求头取出加密的aesKey,然后用私钥解密拿到明文的aesKey,然后对请求数据解密

6.后端用明文aesKey加密响应数据

7.后端把请求过来的id放到响应头

8.前端根据响应头的id,取到对应的aesKey,对响应数据解密

9.前端删除动态的aesKey

三、具体实现案例

1.前端实现AES和RSA的公共方法

        aesUtils.js:


 const CryptoJS = require('crypto-js')

 function GetRandomNum (n) {
    let chars = [
      '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',
      'G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V',
      'W','X','Y','Z','.','?','~','!','@','#','$','%','^','&','*']
    if(n == null) {
      n = 16
    }
    let res = ""
    for(let i = 0; i < n ; i++) {
      let id = Math.ceil(Math.random()*46)
      res += chars[id]
    }
    return res
 }

function GetUuid () {
  let s = []
  const hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    let indexStart = Math.floor(Math.random() * 0x10)
    s[i] = hexDigits.substring(indexStart, indexStart+1)
  }
  s[14] = '4'
  let indexStart = (s[19] & 0x3) | 0x8
  s[19] = hexDigits.substring(indexStart, indexStart+1)
  s[8] = s[13] = s[18] = s[23] = '-'
  return s.join('')
}

function Decrypt (word, key, iv) {
  let key = CryptoJS.enc.Utf8.parse(key)
  let base64 = CryptoJS.enc.Base64.parse(word)
  let src = CryptoJS.enc.Base64.stringify(base64)
  var decrypt = CryptoJS.AES.decrypt(src, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding })
  var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
  return decryptedStr.toString()
}

function Encrypt (word, key, iv) {
  let key = CryptoJS.enc.Utf8.parse(key)
  let src = CryptoJS.enc.Utf8.parse(word)
  var encrypted = CryptoJS.AES.encrypt(src, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding })
  return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
}

export default {
  Decrypt,
  Encrypt,
  GetRandomNum,
  GetUuid,
}

        rsaUtils.js:

import JSEncrypt from 'jsencrypt'

const pubKey = `MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMYWwlqtkWIdA0I/54TP/k1VLgyNwzQB1IvrVKdNfobivHzN02VFGAED1hDSLDiSp4yYrFcXmMFReJJOJ1zjvWECAwEAAQ==`

const encrypt = new JSEncrypt()
encrypt.setPublicKey(pubKey)

function Encrypt(str) {
	let data = encrypt.encrypt(str.toString())
	return data
}

function Decrypt(str) {
	let data = encrypt.decrypt(str.toString())
	return data
}

export default {
  Encrypt,
  Decrypt,
}

 2.前端在拦截请求处,生成AES随机秘钥并加密请求数据,再用RSA加密AES秘钥并放到请求头
        fetch.js:

const aesKeys = {}

instance.interceptors.request.use(function(request) {
	let randomKey = aes.GetRandomNum()

	let reqData
	if (request.data instanceof Object) {
		reqData = JSON.stringify(request.data)
	} else {
		reqData = request.data
	}

	request.data = aes.Encrypt(reqData, randomKey, randomKey)

	let uuid = aes.GetUuid()
	let encryptAesKey = rsa.Encrypt(randomKey)
	request.headers['EncryptAesKey'] = encryptAesKey
	request.headers['uuid'] = uuid

	aesKeys[uuid] = randomKey

	return request
}, function(err) {
	Message({
		message: err,
		type: 'error'
	})
	return Promise.reject(err)
})

instance.interceptors.response.use(function(response) {
	try {
		let uuid = response.headers['uuid']

		let aesKey = aesKeys[uuid]

		delete aesKeys[uuid]

		return JSON.parse(aes.Decrypt(response.data, aesKey, aesKey))
	} catch (e) {
		return response.data
	}
}, function(err) {
	Message({
		message: err,
		type: 'error'
	})
	return Promise.reject(err)
})

3.后端实现AES和RSA的公共方法
        AesUtils.java:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
import org.apache.commons.codec.binary.Base64;

public class AesUtil {
    
    public static String encrypt(String data, String key, String iv) throws Exception {
        try {
 
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
            return new Base64().encodeToString(encrypted);
 
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public static String desEncrypt(String data, String key, String iv) throws Exception {
        try {
            byte[] encrypted1 = new Base64().decode(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString.trim();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String encryptWithKey(String data, String key) throws Exception {
        return encrypt(data, key, key);
    }

    public static String desEncryptWithKey(String data, String key) throws Exception {
        return desEncrypt(data, key, key);
    }

}

        RsaUtils.java:

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;

public class RSAUtils {
    
    /** 算法名称 */
    private static final String     ALGORITHM        = "RSA";
    /** 默认密钥大小 */
    private static final int        KEY_SIZE         = 4096;
    /** 密钥对生成器 */
    private static KeyPairGenerator keyPairGenerator = null;
    
    private static KeyFactory       keyFactory       = null;
    /** 缓存的密钥对 */
    private static KeyPair          keyPair          = null;
    
    /** Base64 编码/解码器 JDK1.8 */
    private static Base64.Decoder   decoder          = Base64.getDecoder();
    private static Base64.Encoder   encoder          = Base64.getEncoder();

    private static final String PRI_KEY = "MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAxhbCWq2RYh0DQj/nhM/+TVUuDI3DNAHUi+tUp01+huK8fM3TZUUYAQPWENIsOJKnjJisVxeYwVF4kk4nXOO9YQIDAQABAkEArOrHJBLpm0UKSDWyq2xJaEZYGVtSsD58xNtcHWN3dNRFWLZWZ9+D31OT0yE0T+dUhBVQFzHh3uDPd3Ax4STIwQIhAOPcBuFP4hoLcCPGvnvl+Co79XRKVkFtlduimiMzxg65AiEA3o2CjUz6TN51P8Q/kkPLHZHj4kB3ZPjNLNdKQusfj+kCIDe6z9/5psZR99p4OIybIYhK4+zOZaxY/ica7PIhLpbZAiEAupudZC2vktTVK2q6g0IlBd5WXlf/xMJ6B6ddtU7BYEECIEzbfR1Ac5zTrxTQ5icmD/ZRChgfhdxToGa21SQscW+K";

    public static final String PEM_CODE_PUB = "MEEwDQYJKoZIhvcNAQEBBQADMAAwLQImDr5/bK6tmdEMYTJXsD/AXIOwE2a9/bfkPvtWUR7vzkvB33tPcEsCAwEAAQ==";

    public static final String PEM_CODE_PRI = "";

    /** 初始化密钥工厂 */
    static {
        try {
            keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
            keyFactory = KeyFactory.getInstance(ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
    
    private RSAUtils() {
    }
    
    public static synchronized Map<String, Object> generateKeyPair() {
        try {
            keyPairGenerator.initialize(KEY_SIZE,
                new SecureRandom(UUID.randomUUID().toString().replaceAll("-", "").getBytes()));
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
        }
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        String publicKeyString = encoder.encodeToString(rsaPublicKey.getEncoded());
        String privateKeyString = encoder.encodeToString(rsaPrivateKey.getEncoded());
        Map<String, Object> keyPairMap = new HashMap<String, Object>();
        keyPairMap.put("public", publicKeyString);
        keyPairMap.put("private", privateKeyString);
        return keyPairMap;
    }
    
    public static synchronized Map<String, Object> generatePKS1KeyPair() {
        Map<String, Object> keyPairMap = new HashMap<String, Object>();
        try {
            keyPairGenerator.initialize(KEY_SIZE,
                new SecureRandom(UUID.randomUUID().toString().replaceAll("-", "").getBytes()));
            keyPair = keyPairGenerator.generateKeyPair();
            PublicKey pub = keyPair.getPublic();
            byte[] pubBytes = pub.getEncoded();
            SubjectPublicKeyInfo spkInfo = SubjectPublicKeyInfo.getInstance(pubBytes);
            ASN1Primitive pubprimitive = spkInfo.parsePublicKey();
            byte[] publicKeyPKCS1 = pubprimitive.getEncoded();
            System.out.println(publicKeyPKCS1.toString());
            
            PrivateKey priv = keyPair.getPrivate();
            byte[] privBytes = priv.getEncoded();
            PrivateKeyInfo pkInfo = PrivateKeyInfo.getInstance(privBytes);
            ASN1Encodable encodable = pkInfo.parsePrivateKey();
            ASN1Primitive priprimitive = encodable.toASN1Primitive();
            byte[] privateKeyPKCS1 = priprimitive.getEncoded();
            System.out.println(privateKeyPKCS1.toString());
          
            keyPairMap.put("public", publicKeyPKCS1);
            keyPairMap.put("private", privateKeyPKCS1.toString());
        
        } catch (Exception e) {
            e.printStackTrace();
        }
        return keyPairMap;
    }
    
    public static PublicKey getPublicKey(String pubKey) {
        try {
            byte[] keyBytes = decoder.decode(pubKey);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static PrivateKey getPrivateKey(String priKey) {
        try {
            byte[] keyBytes = decoder.decode(priKey);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
            return (java.security.interfaces.RSAPrivateKey) keyFactory
                .generatePrivate(pkcs8EncodedKeySpec);
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static String encryptByPublic(byte[] content, PublicKey publicKey) {
        if (publicKey == null) {
            publicKey = (PublicKey) getPublicKey(PEM_CODE_PUB);
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            //该密钥能够加密的最大字节长度
            int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8 - 11;
            byte[][] arrays = splitBytes(content, splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays) {
                stringBuffer.append(Base64Utils.encodeToString(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String encryptByPrivate(byte[] content, PrivateKey privateKey) {
        if (privateKey == null) {
            privateKey = (PrivateKey) getPrivateKey(PEM_CODE_PRI);
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            //该密钥能够加密的最大字节长度
            int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8 - 11;
            byte[][] arrays = splitBytes(content, splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays) {
                stringBuffer.append(Base64Utils.encodeToString(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decryptByPrivate(String content, PrivateKey privateKey) {
        if (privateKey == null) {
            privateKey = (PrivateKey) getPrivateKey(PEM_CODE_PRI);
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            //该密钥能够加密的最大字节长度
            int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8;
            byte[] contentBytes = Base64Utils.decodeFromString(content);
            byte[][] arrays = splitBytes(contentBytes, splitLength);
            StringBuffer stringBuffer = new StringBuffer();
            for (byte[] array : arrays) {
                stringBuffer.append(new String(cipher.doFinal(array)));
            }
            return stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static byte[][] splitBytes(byte[] bytes, int splitLength) {
        //bytes与splitLength的余数
        int remainder = bytes.length % splitLength;
        //数据拆分后的组数,余数不为0时加1
        int quotient = remainder != 0 ? bytes.length / splitLength + 1
            : bytes.length / splitLength;
        byte[][] arrays = new byte[quotient][];
        byte[] array = null;
        for (int i = 0; i < quotient; i++) {
            //如果是最后一组(quotient-1),同时余数不等于0,就将最后一组设置为remainder的长度
            if (i == quotient - 1 && remainder != 0) {
                array = new byte[remainder];
                System.arraycopy(bytes, i * splitLength, array, 0, remainder);
            } else {
                array = new byte[splitLength];
                System.arraycopy(bytes, i * splitLength, array, 0, splitLength);
            }
            arrays[i] = array;
        }
        return arrays;
    }

}

4.后端重写HttpServletRequestWrapper中的getInputStream(),解密拿到请求的明文

import org.apache.commons.lang3.StringUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class XssRequestWrappers extends HttpServletRequestWrapper {
    public XssRequestWrappers(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        Map<String, String> headerMap = getHeadersInfo((HttpServletRequest) super.getRequest());

        String encryptAeskey = headerMap.get("encryptaeskey");
        String aesKey = RSAUtils.decryptByPrivate(encryptAeskey, RSAUtils.getPrivateKey(CommConstants.RSA.PRI_KEY));

        ServletInputStream servletInputStream = super.getInputStream();

        try {
            return decryptReqData(servletInputStream, aesKey);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return servletInputStream;
    }

    private ServletInputStream decryptReqData(ServletInputStream servletInputStream, String aesKey)
            throws Exception {
        StringBuilder jb = new StringBuilder();
        String line;
        BufferedReader reader = new BufferedReader(new InputStreamReader(servletInputStream));
        while ((line = reader.readLine()) != null) {
            jb.append(line);
        }
        String encryptReqData = jb.toString();

        if(StringUtils.isNotBlank(encryptReqData)) {
            String reqData = AesUtil.desEncryptWithKey(encryptReqData, aesKey);
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(reqData.getBytes(StandardCharsets.UTF_8));
            return new ServletInputStream() {
                @Override
                public int read() {
                    return byteArrayInputStream.read();
                }
                @Override
                public boolean isFinished() {
                    return false;
                }
                @Override
                public boolean isReady() {
                    return false;
                }
                @Override
                public void setReadListener(ReadListener listener) {
                }
            };
        }
        return servletInputStream;
    }

    private Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        Locale.setDefault(Locale.ENGLISH);
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement().toLowerCase(Locale.ENGLISH);
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }
}

5.通过ResponseBodyAdvice给响应数据加密处理

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@ControllerAdvice
public class ResponseBodyAdvice implements org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice<Object> {
 
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
 
    try {
           ServletServerHttpRequest request = (ServletServerHttpRequest)serverHttpRequest;
           HttpServletRequest servletRequest = request.getServletRequest();
           Map<String, String> headerNames = RequestUtils.getHeadersInfo(servletRequest);

           String encryptAeskey = headerNames.get("encryptaeskey");
           String aesKey = RSAUtils.decryptByPrivate(encryptAeskey, RSAUtils.getPrivateKey(CommConstants.RSA.PRI_KEY));

           String uuid = headerNames.get("uuid");
           serverHttpResponse.getHeaders().add("uuid", uuid);
           ArrayList<String> list = new ArrayList<>();
           list.add("uuid");
           serverHttpResponse.getHeaders().setAccessControlExposeHeaders(list);

           return AesUtil.encryptWithKey(String.valueOf(o), aesKey);
	   } catch (Exception e) {
		   e.printStackTrace();
	   }
       return o;
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
}


 

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
混合加密是指使用多种加密算法对数据进行加密,以达到更高的安全性。在实际应用,常常使用AESRSA两种加密算法进行混合加密。 具体实现步骤如下: 1. 生成AES密钥,并用该密钥对明文进行加密。 2. 生成RSA密钥对,并使用公钥加密AES密钥。 3. 将经过AES加密的密文和RSA加密AES密钥一起发送给接收方。 4. 接收方使用自己的RSA私钥解密AES密钥。 5. 使用解密后的AES密钥对密文进行解密,得到原始明文。 Java代码实现如下: ```java import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; public class HybridEncryptUtil { // 生成AES密钥 public static SecretKey generateAESKey() throws NoSuchAlgorithmException { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(128); return keyGenerator.generateKey(); } // 生成RSA密钥对 public static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(1024); return keyPairGenerator.generateKeyPair(); } // 使用AES密钥加密数据 public static byte[] encryptAES(byte[] data, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(data); } // 使用AES密钥解密数据 public static byte[] decryptAES(byte[] data, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(data); } // 使用RSA公钥加密数据 public static byte[] encryptRSA(byte[] data, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } // 使用RSA私钥解密数据 public static byte[] decryptRSA(byte[] data, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } // 使用AES密钥加密数据,并使用RSA公钥加密AES密钥 public static byte[][] hybridEncrypt(byte[] data, PublicKey publicKey) throws Exception { SecretKey secretKey = generateAESKey(); byte[] encryptedData = encryptAES(data, secretKey); byte[] encryptedKey = encryptRSA(secretKey.getEncoded(), publicKey); return new byte[][]{encryptedData, encryptedKey}; } // 使用RSA私钥解密AES密钥,并使用AES密钥解密数据 public static byte[] hybridDecrypt(byte[][] encryptedData, PrivateKey privateKey) throws Exception { byte[] encryptedContent = encryptedData[0]; byte[] encryptedKey = encryptedData[1]; byte[] decryptedKey = decryptRSA(encryptedKey, privateKey); SecretKey secretKey = new SecretKeySpec(decryptedKey, "AES"); return decryptAES(encryptedContent, secretKey); } } ``` 使用示例: ```java import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import javax.crypto.SecretKey; public class HybridEncryptTest { public static void main(String[] args) throws Exception { String content = "Hello, World!"; // 生成RSA密钥对 KeyPair keyPair = HybridEncryptUtil.generateRSAKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); // 混合加密 byte[][] encryptedData = HybridEncryptUtil.hybridEncrypt(content.getBytes(), publicKey); // 混合解密 byte[] decryptedData = HybridEncryptUtil.hybridDecrypt(encryptedData, privateKey); String result = new String(decryptedData); System.out.println(result); } } ``` 注意事项: 1. AES密钥长度必须为128位,否则无法与RSA密钥进行混合加密。 2. RSA加密数据长度不能超过密钥长度减去11,否则无法加密,因此在实际应用需要对数据进行分段加密。 3. 在使用密钥加密和解密数据时,需要使用相同的算法和模式,否则无法正确解密数据
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值