一、AES和RSA简单介绍

  • AES:对称加解密,加密解密使用同一个秘钥。
  • RSA:非对称加解密,使用公钥加密数据,只有对应的私钥才能解密,加密方和解密方各自保存秘钥对中的一个。(这里推荐一个RSA密钥对生成器,在线生成无需安装,方便快捷:传送门

二、基本步骤

1、项目结构如下:(完整代码:传送门

aes解密补齐乱码 ios aes解密怎么用_RSA

2、代码示例

  • 前端页面:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>AES、RSA加密</title>
    <script th:src="@{/js/jquery-3.6.0.js}"></script>
    <script th:src="@{/js/crypto-js.js}"></script>
    <script th:src="@{/js/jsencrypt.js}"></script>
</head>
<body>
<h1>加密算法demo</h1>
<h2>AES加密,后台解密</h2>
<input id="aesValue"/>
<button onclick="encryptAes()">加密AES,返回解密后的明文</button>

<h2>RSA加密,后台解密</h2>
<input id="rsaValue"/>
<button onclick="encryptRsa()">加密RSA,返回解密后的明文</button>
</body>
<script>
    /**
     * AES 加密方法
     */
    function encryptAes() {
        // 密钥,后端也用相同的密钥解密
        var secretKey = 'uBdUx82vPHkDKb284d7NkjFoNcKWBuka';
        var encryptedData = CryptoJS.AES.encrypt($("#aesValue").val(), CryptoJS.enc.Utf8.parse(secretKey), {
            iv: CryptoJS.enc.Utf8.parse('1234567887654321'),
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });
        // 加密内容要toString(),返回的才是加密的字符串
        console.info(encryptedData.toString());

        // 后台解密
        $.ajax({
            type: "get",
            url: "/demo/decryptAes",
            data: {value: encryptedData.toString()},
            success: function(data) {
                alert('解密内容是:' + data);
            },
            error: function() {
            }
        });
    }

    /**
     * RSA 加密方法
     */
    function encryptRsa() {
        var encrypt = new JSEncrypt();
        // 设置公钥
        encrypt.setPublicKey('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsRVQfE0mOFCBqthPyNLzJTtENgRAw2O4g7RhWQhms3P+uKHt+Kuff+YaHKpAQ6XiyPmJSAS9joaemvF5ew9k3ZGuDYnXNd3Vwxq9bTHnPAZeTLzVQ1n5iOmid1BR56ENynLkw8LSHgcHPixwvXfJNVHczip/1aXqwAmZS1GKLnJXye1+qv+WeWMcLOAYRVi1sm+nhRV+TzN3o9ykPqiEY8bmAOWo//jD68YgVRWwlnOY+euGzfWV4mhxyVSJ1jjwvM5Aox+HfABHnWPQ/3DdTmtM7NJKAYVhCZOOgQAY/os2OBf8AIC6uHmwFkJvUS4YkUPS5kRE+s1SR3iIxaAeEwIDAQAB');
        // 使用公钥加密,返回加密后的数据
        var encrypted = encrypt.encrypt($("#rsaValue").val());
        console.info(encrypted);

        // 前台解密
        var decrypt = new JSEncrypt();
        // 设置私钥
        decrypt.setPrivateKey('MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCxFVB8TSY4UIGq2E/I0vMlO0Q2BEDDY7iDtGFZCGazc/64oe34q59/5hocqkBDpeLI+YlIBL2Ohp6a8Xl7D2Tdka4Nidc13dXDGr1tMec8Bl5MvNVDWfmI6aJ3UFHnoQ3KcuTDwtIeBwc+LHC9d8k1UdzOKn/VperACZlLUYouclfJ7X6q/5Z5Yxws4BhFWLWyb6eFFX5PM3ej3KQ+qIRjxuYA5aj/+MPrxiBVFbCWc5j564bN9ZXiaHHJVInWOPC8zkCjH4d8AEedY9D/cN1Oa0zs0koBhWEJk46BABj+izY4F/wAgLq4ebAWQm9RLhiRQ9LmRET6zVJHeIjFoB4TAgMBAAECggEAXzpSFPY8Bm6svF4k0Z83aB8t+EpjNW+r6w+WhhVxfTF0mn9iBKbuWA46no2jj31mrqMagyMheMLGChavOFE38bsEuX0VwX7xFEGN+mmqqunVzjiCCv0YptrVJoqH8SL30pXkla1v5vvqljG50vnWtxi1wBy0sATQb8L5r7pCr+SiNAlbt2X7ePyk7EkKTpon6Bl2249dZnDedOdz+wH/lQs9rGxvtqeBqbqWCj7GsxEuQysSBtnvsta/vw7M+/VvEiRh5MUrCVvJrt/thJwWMY57e01iHLuURf6xnrZqvYPrCcz5i2MVbXVawyCIq5TJAJLyeGRkXGXIvtqbkM3xAQKBgQDfYq0i4yWmnB88NehdnnTb3Tmtxtd3A+2tHzJF3dYAc1a6zAFXqTDPbt5SsqoonIbbBAzdvREHCWw4yc8XGIx18/tdxeF385V/umpPkhM+v+QYmFOLDjdODD3JByIccMMW392Zrhe6A1JA5b83XjUJs1wwFogrIY/HWElHlZ1tkwKBgQDK8Ahvl0mRnbSgA6aQ1iUzOiz7tEZRHFiep0kis8pLsePxL3UsKXP5rgssMk+hj4oLsDqRi9OXyKVFIy7N/b7DNUqnAG9y8w1ASZYvHdgJ3GndjOSESWQia83RDxaVTHP+6AQVkcSoz6HjA/JZh3FX34ogyThX/g10eEeuD/zdgQKBgDAGvQaFI3Egm66MQHrwOFuUwnPUDjruQ0k3Lc3Lldje80SR27AHFhFi2rWY5/B3Rp8LzeBWZ7TFl9jVuopSotAxNlfA1Wq+meOuJnEZDL4u71FCXqPE2KsVAquXtwO6Upc2ZiRGQ5+gWyzMuEGlJW4Ce81y6q+rNYg8OPUE+6W1AoGAXuSwvSV8BDg/PteWKoHIMVURtb0NaF4d3koQ+8YgYRbUpHHxk23qyiSlGsyHyd8pyN9l86rzjTUIevTBrRbq/bLMrpyYgKLAXoBKVsvYunuzkSKRtH3w8duBCTHJ+JQgZWCukDtyPxGf/FxbFZws1s8zcrNEwniMaBraQb0+G4ECgYANbFMZEFxZ/zy3BAiWQvGMWTKTocopmaMGhvHrqoSvsXea4HFBPfq1YF32SzamB+5xVb6ePWLK7Vl8wYSHXLkyh6kWO8FJz9Q3VmmfGhMQe17+x4/D6zPg68cKmghhnzupKRFv2pZPpNIyGZ2GRpG28+AtIvnjWFzi1NJSowKe6w==');
        var uncrypted = decrypt.decrypt(encrypted);
        console.info(uncrypted);

        // 后台解密
        $.ajax({
            type: "get",
            url: "/demo/decryptRsa",
            data: {value: encrypted},
            success: function(data) {
                alert('解密内容是:' + data);
            },
            error: function() {
            }
        });
    }
</script>
</html>
  • AesUtils:
package com.fds.system.utils;
/**
* @author fds
* @date 2020-09-16 11:17
**/
public class AesUtils {

   /**
    * 密钥, 256位32个字节
    */
   public static final String DEFAULT_SECRET_KEY = "uBdUx82vPHkDKb284d7NkjFoNcKWBuka";

   private static final String AES = "AES";

   /**
    * 初始向量IV, 初始向量IV的长度规定为128位16个字节, 初始向量的来源为随机生成.
    */
   private static final byte[] KEY_VI = "1234567887654321".getBytes();

   /**
    * 加密解密算法/加密模式/填充方式
    */
   private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";

   private static java.util.Base64.Encoder base64Encoder = java.util.Base64.getEncoder();
   private static java.util.Base64.Decoder base64Decoder = java.util.Base64.getDecoder();

   static {
       java.security.Security.setProperty("crypto.policy", "unlimited");
   }

   /**
    * AES加密
    */
   public static String encode(String key, String content) {
       try {
           javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
           javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
           cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, secretKey, new javax.crypto.spec.IvParameterSpec(KEY_VI));

           // 获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
           byte[] byteEncode = content.getBytes(java.nio.charset.StandardCharsets.UTF_8);

           // 根据密码器的初始化方式加密
           byte[] byteAES = cipher.doFinal(byteEncode);

           // 将加密后的数据转换为字符串
           return base64Encoder.encodeToString(byteAES);
       } catch (Exception e) {
           e.printStackTrace();
       }
       return null;
   }

   /**
    * AES解密
    */
   public static String decode(String key, String content) {
       try {
           javax.crypto.SecretKey secretKey = new javax.crypto.spec.SecretKeySpec(key.getBytes(), AES);
           javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CIPHER_ALGORITHM);
           cipher.init(javax.crypto.Cipher.DECRYPT_MODE, secretKey, new javax.crypto.spec.IvParameterSpec(KEY_VI));

           // 将加密并编码后的内容解码成字节数组
           byte[] byteContent = base64Decoder.decode(content);
           // 解密
           byte[] byteDecode = cipher.doFinal(byteContent);
           return new String(byteDecode, java.nio.charset.StandardCharsets.UTF_8);
       } catch (Exception e) {
           e.printStackTrace();
       }
       return null;
   }
}
  • RsaUtils:
package com.fds.system.utils;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import java.util.Base64;

/**
* @author: fds
* @date: 2021/7/13
* @description: RSA非对称加密工具类
*/
public class RsaUtils {

   /**
    * RSA公钥加密
    *
    * @param str       加密字符串
    * @param publicKey 公钥
    * @return 密文
    * @throws Exception 加密过程中的异常信息
    */
   public static String encrypt(String str, String publicKey) throws Exception {
       // base64编码的公钥
       byte[] decoded = Base64.getDecoder().decode(publicKey);
       RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
       // RSA加密
       Cipher cipher = Cipher.getInstance("RSA");
       cipher.init(Cipher.ENCRYPT_MODE, pubKey);
       return Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes("UTF-8")));
   }

   /**
    * RSA私钥解密
    *
    * @param str        加密字符串
    * @param privateKey 私钥
    * @return 明文
    * @throws Exception 解密过程中的异常信息
    */
   public static String decrypt(String str, String privateKey) throws Exception {
       // 64位解码加密后的字符串
       byte[] inputByte = Base64.getDecoder().decode(str);
       // base64编码的私钥
       byte[] decoded = Base64.getDecoder().decode(privateKey);
       RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
       // RSA解密
       Cipher cipher = Cipher.getInstance("RSA");
       cipher.init(Cipher.DECRYPT_MODE, priKey);
       return new String(cipher.doFinal(inputByte));
   }
}
  • DemoController:
package com.fds.system.controller;

import com.fds.system.utils.AesUtils;
import com.fds.system.utils.RsaUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/demo")
public class DemoController {

   @Value("${rsa.secretKey}")
   private String secretKey;

   /**
    * aes解密接口
    * @param value
    * @return
    */
   @GetMapping("/decryptAes")
   public String decryptAes(String value) {
       return AesUtils.decode(AesUtils.DEFAULT_SECRET_KEY, value);
   }

   /**
    * rsa解密接口
    * @param value
    * @return
    */
   @GetMapping("/decryptRsa")
   public String decryptRsa(String value) throws Exception {
       return RsaUtils.decrypt(value, secretKey);
   }
}

最后作者本人还有一个计划小程序。给自己一个计划,每天有盼头,喜欢的可以扫一扫,蟹蟹大家的支持。