资讯详情

SpringBoot接口加密与解密

文章目录

  • 1.对称/不对称加密
    • 1、简介
    • 2、RSA和AES介绍
      • 2.1 RSA
      • 2.2 AES
    • 3、RSA/AES组合
    • 4、Base64编码的作用
  • 二、Java实现加解密/加验签
    • 1、全局Config
    • 2、RSA非对称加密
    • 3、AES对称加密
  • 三、加解密 starter实战
    • 1、介绍
    • 2、前期准备
      • 2.1 引入依赖
      • 2.2 封装公共相应类
      • 2.3 定义加解密工具
      • 2.4 定义两个注释
      • 2.5 设置自定义key
    • 加密和解密接口
      • 3.1 介绍
      • 3.2 接口加密
      • 3.3 接口解密
    • 4、打包发布starter
      • 4.1 定义自动配置类
      • 4.2 在线发布使用
    • 5.使用新项目

1.对称/不对称加密

1、简介

只有一个密钥,加密和解密使用相同的密钥,因此称为对称加密。

有两个秘密钥匙,一个是公钥,另一个是私钥。不对称的特点是,公钥加密的私钥可以解密,但如果私钥加密,公钥无法解决,只能验证私钥是否加密

有两种常见的加密方法,一种是,一种是

2、RSA和AES介绍

2.1 RSA

:只需交换公钥;公钥/秘钥机制、公钥加密、私钥解密(或私钥加密、公钥解密);公钥加密,私钥解密;私钥签名,公钥验证

:解密速度慢,尤其是解密

2.2 AES

:用同一把钥匙加解密

:速度快,效率高;

:密钥交换问题

3、RSA/AES组合

这是因为一旦给出了秘钥,了。,即使提供公钥,其他人也无法解密数据,但

在实际使用过程中经常使用,安全传输AES避免秘钥RSA加密的慢速度

  • 随机生成AES秘钥字符串

  • 使用RSA公钥加密AES再用秘钥AES密钥加密真实内容

  • 把skey=加密的AES秘钥,body=AES秘密钥加密的内容已经传过去

  • 对面使用RSA私钥解密AES然后用秘钥AES密钥解密内容

4、Base64编码的作用

,因此,我们通常需要重用加密数据 Base64 编码算法,。换言之,AES 或者RSA加密方法的返回值是一种 Base64 编码后的字符串,AES或者RSA 解密方法的参数也是一个 Base64 编码后的字符串,先对该字符串进行解码,然后再解密。

二、Java实现加解密/加验签

1、全局Config

public class Config { 
              public static final String AES_ALGORITHM = "AES/CBC/PKCS5Padding";     public static final String RSA_ALGORITHM = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";     //必须是PKCS8格式     public static final String CLIENT_PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAO/8ucCgOTJ7DCPC"               "rCCL1VKDnUX61QnxwbAvpGp1/lletEIcjUouM7F0VvMHzViNLvpw7N7NBHPa 5gO"               "js68t9hKMUh a6RTE34SWIqSDRPCzDKVWugsFb04o3vRl3rZ1z6B QDdW7xwOhEr"               "PPoEqmjjIOjQPcU6xs0SPzSimOa1AgMBAAECgYAO5m0OBaSnerZNPhf7yVLMVbmd"               "D67MeEMjUkHuDjdlixi8BhPLqESzXtrLKg/Y0KM7D2nVh3sgSldWoIjDUzpCx8Z2"               "yHLU1K2wakMdBgEF3xeJPxxZRpP earl0SyLTA4hMxl48uAjn/mkPgzoMgQkqyQz" +
            "5HOWjjsCLJFyEvqmoQJBAP5cBk0KXpHnCMgOupbi/pXDyaF1o+dCE97GaEdrV/0P" +
            "uwDfYDYfY3wzd1QM7C4b4MmE+SNVpC0W9PyaMONJlN0CQQDxiPiGdwX9actMNJea" +
            "JZ+k3BjCN+mM6Px7j/mtYcXWNZkyCXSXUBI62drZ0htenrh2qwichMlMgNJClvG6" +
            "Gu+5AkEA30R7q2gstrkrNh/nnMZHXcJr3DPc2QNhWayin/4TT+hc51krpJZMxxqN" +
            "5dMqBRcnavwzi9aCs6lxBcF6pCdUaQJANhd7uPls4PzRZ6abkQz9/LjB3rUQ29rN" +
            "uIpc2yR7XuawAVG2x7BJ9N4XMhLoyD75hrH1AsCGKFjtPbZ6OjiQGQJAF2DbIodC" +
            "uYb6eMZ8ux1Ab0wBEWWc5+iGgEVBNh22uZ/klE1/C0+KKzZhqgzaA/vPapq6dhuJ" +
            "sNXlJia10PwYrQ==";

    public static final String CLIENT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDv/LnAoDkyewwjwqwgi9VSg51F" +
            "+tUJ8cGwL6Rqdf5ZXrRCHI1KLjOxdFbzB81YjS76cOzezQRz2vuYDo7OvLfYSjFI" +
            "fmukUxN+EliKkg0TwswylVroLBW9OKN70Zd62dc+gfkA3Vu8cDoRKzz6BKpo4yDo" +
            "0D3FOsbNEj80opjmtQIDAQAB";

    public static final String SERVER_PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPGkxlAJPKR3BRxT" +
            "PIeB3pDv117j8XbpuEik5UIOlY3GUtAV1sad5NNDUAnP/DB80yAQ8ycm9Xdkutuo" +
            "f25Xlb7w0bRQNpfJlijx9eF8PsB6t63r8KAfWJlqbNHgN8AMK9P5XzVyN4YiEnUl" +
            "Jh/EYiwLiYzflNnmnnfRrI4nUo8fAgMBAAECgYEAvwTxm81heeV4Tcbi33/jUBG4" +
            "4BMzCzyA6DQp4wkiYju3tTS+Xq3seLEKcWdPxYi3YO7lODsM6j/fksrlSXXFMe1i" +
            "ZAF3FNuDVZPz2zdFYS8vh6kdlDHMJAUnU/POMMWJ880MQDtkwTuzH8Tao8OKcAP4" +
            "kc0QuG00wOrmuE+5gZECQQD9bqZkJsN+tj3+pxs57azy6B6gOqgm54/ujB+u63XU" +
            "rO9Sf57asgF4OfUFltaVhjlUMSrWcgp6f4HSy7hBSKJpAkEA9BeML5iDIHOgTIws" +
            "+ID55ELbzO7A/YtcYnUU09mkKCdonMXbXke+EhLApf5vX9ZmreoEfJCdsTnMEcQi" +
            "fkjkRwJBALpf2TXl2/cfhs/zjG45f+rTEVK8UFTsDklb+yDkQC87TnTZLbWfGr2T" +
            "wcFugDhOEXL9BYfXLiWQB6VB9Crug6ECQGEmTiFTbj0oSBCvaeauTsdO5PS3whAn" +
            "u2lkeBmpcfCZXsWm6hyoKTpARHTMw789Mjjd/1Mkq96xxkr76U6h7FkCQHRc2elg" +
            "Dh84wqHIptwa+moosVvd7aSzktuOB4CQRO10qKkSHVFuI+sl47A4KGzH/nX9ydUm" +
            "tpsTnQAlXwBczd4=";

    public static final String SERVER_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDxpMZQCTykdwUcUzyHgd6Q79de" +
            "4/F26bhIpOVCDpWNxlLQFdbGneTTQ1AJz/wwfNMgEPMnJvV3ZLrbqH9uV5W+8NG0" +
            "UDaXyZYo8fXhfD7Aeret6/CgH1iZamzR4DfADCvT+V81cjeGIhJ1JSYfxGIsC4mM" +
            "35TZ5p530ayOJ1KPHwIDAQAB";

}

2、RSA非对称加密

import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.security.*;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.springframework.util.Base64Utils;

public class RSACipher { 
        

    /** * 获取公钥 * @param key 密钥字符串(经过base64编码) * @return 公钥 */
    public static PublicKey getPublicKey(String key) throws Exception { 
        
        // 按照X.509标准对其进行编码的密钥
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64Utils.decode(key.getBytes()));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 生成公钥
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /** * 获取私钥 * @param key 密钥字符串(经过base64编码) * @return 私钥 */
    public static PrivateKey getPrivateKey(String key) throws Exception { 
        
        // 按照PKCS8格式标准对其进行编码的密钥,首先要将key进行base64解码
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64Utils.decode(key.getBytes()));
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        // 生成私钥
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /** * 加密方法 * @param publicKey 公钥 * @param raw 待加密明文 * @return 加密后的密文 */
    public static byte[] encrypt(String publicKey, byte[] raw) throws Exception { 
        
        Key key = getPublicKey(publicKey);
        Cipher cipher = Cipher.getInstance(Config.RSA_ALGORITHM);
        // 初始化
        cipher.init(Cipher.ENCRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
        byte[] encryption = cipher.doFinal(raw);
        // 最后将加密后的数据进行base64编码
        return Base64Utils.encode(encryption);
    }

    /** * 解密方法 * @param privateKey 私钥 * @param enc 待解密密文 * @return 解密后的明文 */
    public static byte[] decrypt(String privateKey, byte[] enc) throws Exception { 
        
        Key key = getPrivateKey(privateKey);
        Cipher cipher = Cipher.getInstance(Config.RSA_ALGORITHM);
        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
        // 先进行base64解密,然后解码
        return cipher.doFinal(Base64Utils.decode(enc));
    }

    /** * 签名 * @param privateKey 私钥 * @param content 要进行签名的内容 * @return 签名 */
    public static String sign(String privateKey, byte[] content) { 
        
        try { 
        
            // privateKey进行base64编码,然后生成PKCS8格式私钥
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64Utils.decode(privateKey.getBytes()));
            KeyFactory key = KeyFactory.getInstance("RSA");
            PrivateKey priKey = key.generatePrivate(priPKCS8);
            // 签名摘要算法
            Signature signature = Signature.getInstance("SHA256WithRSA");
            // 用私钥初始化此对象以进行签名
            signature.initSign(priKey);
            // 使用指定的字节数组更新签名或验证
            signature.update(content);
            // 获得签名字节
            byte[] signed = signature.sign();
            // 进行base64编码返回
            return new String(Base64Utils.encode(signed));
        } catch (Exception e) { 
        
            e.printStackTrace();
        }
        return null;
    }

    /** * 验签 * @param publicKey 公钥 * @param content 要验签的内容 * @param sign 签名 * @return 验签结果 */
    public static boolean checkSign(String publicKey, byte[] content, String sign) { 
        
        try { 
        
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            // 进行base64解码
            byte[] encodedKey = Base64Utils.decodeFromString(publicKey);
            // 生成公钥
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            // 签名摘要算法
            Signature signature = Signature.getInstance("SHA256WithRSA");
            // 用公钥初始化签名
            signature.initVerify(pubKey);
            // 使用指定的字节数组更新签名或验证
            signature.update(content);
            // base64解码后进行验证
            return signature.verify(Base64Utils.decodeFromString(sign));
        } catch (Exception e) { 
        
            e.printStackTrace();
        }
        return false;
    }

    public static void main(String[] args) throws Exception { 
        
        //客户端代码
        String text = "hello";
        //使用服务端公钥加密
        byte[] encryptText = RSACipher.encrypt(Config.SERVER_PUBLIC_KEY, text.getBytes());
        System.out.println("加密后:\n" + new String(encryptText));
        //使用客户端私钥签名
        String signature = RSACipher.sign(Config.CLIENT_PRIVATE_KEY, encryptText);
        System.out.println("签名:\n" + signature);
        //服务端代码
        //使用客户端公钥验签
        boolean result = RSACipher.checkSign(Config.CLIENT_PUBLIC_KEY, encryptText, signature);
        System.out.println("验签:\n" + result);
        //使用服务端私钥解密
        byte[] decryptText = RSACipher.decrypt(Config.SERVER_PRIVATE_KEY, encryptText);
        System.out.println("解密后:\n" + new String(decryptText));
    }
}

输出结果

加密后:
ODdEkwo1RgRW8UMoHXPKe9Gwcp6lTCkg4P/Ra3gfkrO+Fw6pSgo0H54nMC5sYSsoUVy1wy2/QXeLSwR6Obfl7SU7DeW+XdGee83O2kgdsDQPbYFwlPYTd0cdOmWwZxtgEOIB9d5G75Iut4kci15vrhXZVtku92U+7aNwtYimSDQ=
签名:
RL1qIScizRyu79/y+r2TN2FL/bSQDxnDj4JlDwSZM6XZR7CL7u5ZjLNHbsSYpHaCv9qKMS4ump50LyF+go05dsPjWZOvFNkgcm9LepkDP1qm8AzKdTGwlzhdBmy2397Ed8uBrQocFGj/721Y2xM/Db0nt7r54zKZkDXbMMlsd9k=
验签:
true
解密后:
hello

3、AES对称加密

import org.springframework.util.Base64Utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class AESCipher { 
        

    public static SecureRandom random = new SecureRandom();

    /** * 获取随机16位key,key必须要是10的整数倍,否则会出错 */
    public static String getRandom(int length) { 
        
        StringBuilder ret = new StringBuilder();
        for (int i = 0; i < length; i++) { 
        
            // 输出字母还是数字
            boolean isChar = (random.nextInt(2) % 2 == 0);
            // 字符串
            if (isChar) { 
        
                // 取得大写字母还是小写字母
                int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
                ret.append((char) (choice + random.nextInt(26)));
            } else { 
         // 数字
                ret.append(random.nextInt(10));
            }
        }
        return ret.toString();
    }

    /** * 加密方法,使用key充当向量iv,增加加密算法的强度 * 更加安全 * @param key 密钥 * @param raw 需要加密的内容 * @return */
    public static String encrypt(byte[] key, String raw) throws Exception { 
        
        // 第一次加密
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        byte[] enCodeFormat = secretKey.getEncoded();
        // 获取二次加密的key
        SecretKeySpec secondSecretKey = new SecretKeySpec(enCodeFormat, "AES");
        Cipher cipher = Cipher.getInstance(Config.AES_ALGORITHM);
        // 向量iv,增加加密算法的强度
        IvParameterSpec iv = new IvParameterSpec(key);
        // 初始化加密器
        cipher.init(Cipher.ENCRYPT_MODE, secondSecretKey, iv);
        // 加密
        byte[] result = cipher.doFinal(raw.getBytes());
        // 进行base64编码
        return Base64Utils.encodeToString(result);
    }

    /** * 解密方法,使用key充当向量iv,增加加密算法的强度 * @param key 密钥 * @param enc 待解密内容 * @return */
    public static String decrypt(byte[] key, String enc) throws Exception { 
        
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        byte[] enCodeFormat = secretKey.getEncoded();
        // 二次加密
        SecretKeySpec secondSecretKey = new SecretKeySpec(enCodeFormat, "AES");

        Cipher cipher = Cipher.getInstance(Config.AES_ALGORITHM);
        IvParameterSpec iv = new IvParameterSpec(key);
        // 初始化
        cipher.init(Cipher.DECRYPT_MODE, secondSecretKey, iv);
        // 首先进行base64解码
        byte[] bytes = Base64Utils.decodeFromString(enc);
        // 解密
        byte[] result = cipher.doFinal(bytes);
        return new String(result);
    }

    public static void main(String[] args) throws Exception { 
        

        //客户端代码
        String text = "hello";
        //随机生成16位aes密钥,也可以自己指定16位
        byte[] aesKey = getRandom(16).getBytes();

        String encryptText = AESCipher.encrypt(aesKey, text);
        System.out.println("加密后:\n" + encryptText);
        String decryptText = AESCipher.decrypt(aesKey, encryptText);
        System.out.println("解密后:\n" + decryptText);
    }
}

输出结果

加密后:
hwkYAF9eXj/dytmDBD30xg==
解密后:
hello

三、加解密 starter实战

1、介绍

加密解密本身并不是难事,问题是在何时去处理?定义一个过滤器,将请求和响应分别拦截下来进行处理也是一个办法,这种方式虽然粗暴,但是灵活,因为可以拿到一手的请求参数和响应数据。不过 SpringMVC 中给我们提供了 ResponseBodyAdviceRequestBodyAdvice,利用这两个工具可以对请求和响应进行预处理,非常方便。

参考: RSA+AES混合加密-JavaWebSpringBoot自定义starter

2、前期准备

2.1 引入依赖

因为我们这个工具是为 Web 项目开发的,以后必然使用在 Web 环境中,所以这里添加依赖时 scope 设置为 provided

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <scope>provided</scope>
    <version>2.7.0</version>
</dependency>

  • compile:默认值 他表示被依赖项目需要参与当前项目的编译,还有后续的测试,运行周期也参与其中,是一个比较强的依赖。打包的时候通常

标签: dqp9051多参变送器uyb型高压电容物位变送器ljb40电感式传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台