Spring Boot整合RSA加密数据传输

news/2024/11/15 3:33:12/

简介

吹水时间开始了,是这样的,公司自研开发一个app,因为要运营和上架需要办理安全评估,办理中说到公司app有可能会泄露用户信息,对用户信息没有加密,遇到抓包的可能会导致用户信息泄露,这时我想到了RSA加密数据来保护用户信息,所以自己使用好像有点效果。

一、简单使用RSA加密解密

RSA是jdk自带的,不需要依赖

public class RSA{private static Map<String, String> map = new HashMap<>();public static void main(String[] args)  throws Exception {String content = "我喜欢你";genKeyPair();//加密String publicKey = Encryption(content, map.get("publicKey"));System.out.println("加密后:"+publicKey);//解密System.out.println("解密后:"+Decryption(publicKey,map.get("privateKey")));}private static String Encryption(String content,String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {byte[] decodeBase64 = Base64.decodeBase64(publicKey);PublicKey rsa = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decodeBase64));Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.ENCRYPT_MODE,rsa);String outStr  = Base64.encodeBase64String(cipher.doFinal(content.getBytes()));return outStr;}private static String Decryption(String publicKey, String privateKey)throws Exception{byte[] publicKeyByte = Base64.decodeBase64(publicKey.getBytes("UTF-8"));byte[] privateKeyByte = Base64.decodeBase64(privateKey.getBytes("UTF-8"));RSAPrivateKey generatePublic = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyByte));Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, generatePublic);return new String(cipher.doFinal(publicKeyByte));}/*** 随机生成密钥对* @throws NoSuchAlgorithmException*/public static void genKeyPair() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(1024);KeyPair keyPair = keyPairGenerator.generateKeyPair();//私钥PrivateKey privateK = keyPair.getPrivate();//公钥PublicKey publicK = keyPair.getPublic();//PrivateKey2StringString privateKey = new String(Base64.encodeBase64(privateK.getEncoded()));//PublicKey2StringString publicKey = new String(Base64.encodeBase64(publicK.getEncoded()));System.out.println("公钥:"+publicKey);System.out.println("私钥:"+privateKey);map.put("publicKey",publicKey);map.put("privateKey",privateKey);}
}

结果:
在这里插入图片描述

二、Spring Boot 整合 RSA

可以自己生成一个公钥和私钥,也可以在网站中在线生成:http://www.metools.info/code/c80.html
在这里插入图片描述

application.yml

#swagger
lanys:swagger:title: 牟某公司description: 牟某公司termsOfServiceUrl: https://eurasia.plus/swagger-ui.htmlContactName: xxxContactUrl: https://eurasia.plus/swagger-ui.htmlContactEmail: 1090613735@qq.comversion: 1.0public:kay: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJVBeO0vImDyMvmRV7bgQJxhzOkLtAAUv6UJSMBP3YtWj6/5DNjaD5Ezt7OXqQ/wz9b+FWTNECsCRC7Nc/kvqiIfHZp4yZYtlzXUbRJk0iu4Y1lv6oKHOXjjnxCjmZwSgXuuDOChNMwqv9GhOQSo5X4HNmrUdTSbAUxfJMfu6WMwIDAQABprivate:kay: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMlUF47S8iYPIy+ZFXtuBAnGHM6Qu0ABS/pQlIwE/di1aPr/kM2NoPkTO3s5epD/DP1v4VZM0QKwJELs1z+S+qIh8dmnjJli2XNdRtEmTSK7hjWW/qgoc5eOOfEKOZnBKBe64M4KE0zCq/0aE5BKjlfgc2atR1NJsBTF8kx+7pYzAgMBAAECgYEAnwoh7f5vsWcF2aTplm6rG/l3aipk8UPU/DFJl26eBOIRwy29+tMl1Xy+4THfw8jnPxFxhZX7Ck+Q5Zlo1FzMRX3Z6ltqCy5H58n4KI7L85MI+dO5l8tjCtxFgNd7NY1gwRjKCjWUsdKqOHzs/+vaeZR1kp2feljTpMBzGGPqS4ECQQD3kU7Er79XuHpk6qK56ihiLT6O8ZnZzhBPRCHq89MIDmt2s13RnSfxEeLZpKlmKLC7VYbZeypoiLxKOdRq1X9BAkEA0C+Y6wUM6h3VC+HzrH5/x++6siHRFwwnDp4U9VmPeesa2a84krNaqptMZtPcm4wr0heDzr5PLksfrSUoYJdscwJAIrBiqB60IfeAdumFuaU82Vzbmi3yT9mW4XR7iC94D3XtyukhKUDrGtVVwwdWkTD8apN2XLzsWU9nisMFp56YwQJAFqFV6hY+dSSRCB2js1h842r3zG1IoUy84iXk+Vam9gXMgWU+rRO6A1mmUHcvP+lYyhmsRkkBqnKYGuYzIWzUaQJBAII0gYs7yRJ4FckmnehD1bMdpgsivlO03qimh7V+fCePG8MMZSq5NFNDP0rogNyo/HLxk5V+tPT05bitJJmHTGM=

注意:公钥和私钥要放为一行,不然会报错。

SecurityParameter

/*** @author lanys* @Description:* @date 22/7/2021 上午11:37*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Mapping
@Documented
public @interface SecurityParameter {/*** 入参是否解密,默认是解密*/boolean inDecode() default true;/*** 返回数据是否加密,默认加密*/boolean outEncode() default true;
}

RsaDecodeRequestBodyAdvice

请求我们接口前做数据处理

/*** @author lanys* @Description:* @date 22/7/2021 上午11:26*/
@ControllerAdvice("com.example.materialboot.modules.usercontroller.conterller")
@Slf4j
public class RsaDecodeRequestBodyAdvice implements RequestBodyAdvice {@Value("${lanys.private.kay}")public String privateKay;@Overridepublic boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return true;}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {boolean encode = false;if (methodParameter.getMethod().isAnnotationPresent(SecurityParameter.class)) {SecurityParameter methodAnnotation = methodParameter.getMethodAnnotation(SecurityParameter.class);encode = methodAnnotation.inDecode();}if (encode) {log.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密");return new MyHttpInputMessage(httpInputMessage);} else {return httpInputMessage;}}@Overridepublic Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return body;}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {return body;}class MyHttpInputMessage implements HttpInputMessage {private HttpHeaders httpHeaders;private InputStream inputStream;public MyHttpInputMessage(HttpInputMessage httpInputMessage) throws IOException {this.httpHeaders = httpInputMessage.getHeaders();String easpString = easpString(IOUtils.toString(httpInputMessage.getBody(), "UTF-8"));this.inputStream = IOUtils.toInputStream(RSAUtils.decryptDataOnJava(easpString,privateKay));}@Overridepublic InputStream getBody() throws IOException {return this.inputStream;}@Overridepublic HttpHeaders getHeaders() {return this.httpHeaders;}/**** @param requestData* @return*/public String easpString(String requestData){if (requestData != null && !requestData.isEmpty()){String s = "{\"requestData\":";if (!requestData.startsWith(s)){throw new RuntimeException("参数【requestData】缺失异常!");}int closeLen = requestData.length()-1;int openLen = "{\"requestData\":".length();String substring = StringUtils.substring(requestData, openLen, closeLen);return substring;}return  null;}}
}

EncodeResponseBodyAdvice

获取数据响应时做处理

/*** @author lanys* @Description: 返回数据加密* @date 22/7/2021 上午11:26*/
@Component
@ControllerAdvice("com.example.materialboot.modules.usercontroller.conterller")
@Slf4j
public class EncodeResponseBodyAdvice implements ResponseBodyAdvice {@Autowiredprivate RsaUtil rsaUtil;@Value("${lanys.public.kay}")public String publicKay;@Value("${lanys.private.kay}")public String privateKay;/*** 是否支持这个类* @param methodParameter* @param aClass* @return*/@Overridepublic boolean supports(MethodParameter methodParameter, Class aClass) {//默认是不使用,改为truereturn true;}/*** 返回前处理* @param body* @param methodParameter* @param mediaType* @param aClass* @param serverHttpRequest* @param serverHttpResponse* @return*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {log.info("------响应数据加密-------");boolean encode = false;if (methodParameter.getMethod().isAnnotationPresent(SecurityParameter.class)) {//获取注解配置的包含和去除字段SecurityParameter serializedField = methodParameter.getMethodAnnotation(SecurityParameter.class);//出参是否需要加密encode = serializedField.outEncode();}if (encode) {log.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行加密");ObjectMapper objectMapper = new ObjectMapper();try {//获取内容String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(body);// 生成一个解数据的秘钥String aseKey = getRandomString(16);// 将公钥和(生成一个解数据的秘钥)进行加密String encrypted = RSAUtils.encryptedDataOnJava(aseKey, publicKay);// 将响应数据和(生成一个解数据的秘钥)加密String requestData = AesEncryptUtils.encrypt(result, aseKey);System.out.println("解密:"+AesEncryptUtils.decrypt(requestData,aseKey));Map<String, String> map = new HashMap<>();map.put("encrypted", encrypted);map.put("requestData", requestData);return map;} catch (Exception e) {e.printStackTrace();log.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常:" + e.getMessage());}}return body;}/*** 创建指定位数的随机字符串* @param length 表示生成字符串的长度* @return 字符串*/public static String getRandomString(int length) {String base = "abcdefghijklmnopqrstuvwxyz0123456789";Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(base.length());sb.append(base.charAt(number));}return sb.toString();}
}

RSAUtils

public class RSAUtils {/*** 加密算法RSA*/public static final String KEY_ALGORITHM = "RSA";/** *//*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 117;/** *//*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/*** 私钥解密* @param encryptedData* @param privateKey* @return* @throws Exception*/public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(privateKey);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.DECRYPT_MODE, privateK);int inputLen = encryptedData.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();return decryptedData;}/*** java端私钥解密*/public static String decryptDataOnJava(String data, String PRIVATEKEY) {String temp = "";try {byte[] rs = Base64.decodeBase64(data);temp = new String(RSAUtils.decryptByPrivateKey(rs, PRIVATEKEY),"UTF-8");} catch (Exception e) {e.printStackTrace();}return temp;}/*** 公钥加密* @param data* @param publicKey* @return* @throws Exception*/public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(publicKey);Key publicK = KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(new X509EncodedKeySpec(keyBytes));// 对数据加密Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, publicK);int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_ENCRYPT_BLOCK;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}/*** java端公钥加密*/public static String encryptedDataOnJava(String data, String PUBLICKEY) {try {data = Base64.encodeBase64String(encryptByPublicKey(data.getBytes(), PUBLICKEY));} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return data;}}

AesEncryptUtils

前端工具:前端传过来的数据也是加密的,我们也会解密

public class AesEncryptUtils {//参数分别代表 算法名称/加密模式/数据填充方式private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";/*** 加密* @param content 加密的字符串* @param encryptKey key值* @return* @throws Exception*/public static String encrypt(String content, String encryptKey) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128);Cipher cipher = Cipher.getInstance(ALGORITHMSTR);cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));byte[] b = cipher.doFinal(content.getBytes("utf-8"));// 采用base64算法进行转码,避免出现中文乱码return Base64.encodeBase64String(b);}@Value("${lanys.public.kay}")public String publicKay;@Value("${lanys.private.kay}")public String privateKay;/*** 解密* @param encryptStr 解密的字符串* @param decryptKey 解密的key值* @return* @throws Exception*/public static String decrypt(String encryptStr, String decryptKey) throws Exception {KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128);Cipher cipher = Cipher.getInstance(ALGORITHMSTR);cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));// 采用base64算法进行转码,避免出现中文乱码byte[] encryptBytes = Base64.decodeBase64(encryptStr);System.out.println(encryptBytes.length);byte[] decryptBytes = cipher.doFinal(encryptBytes);return new String(decryptBytes);}
}

2.读入数据

代码如下(示例):

data = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

UserController

/*** @ClassName UserController* @Author lanys* @Data 1/4/2021 下午4:56*/
@Api(tags = "用户管理")
@RestController
@RequestMapping("v1/user")
public class UserController {@Autowiredprivate SysUserService userService;@SecurityParameter(inDecode = false,outEncode = true)@GetMapping("list")@RequiresPermissions("sys:user:save,sys:role:select")@ApiImplicitParams({ @ApiImplicitParam(name = HttpHeaders.AUTHORIZATION, value = "token", required = true, paramType = "header")})public Result UserList(){return Result.success().put(userService.userList());}}

这时响应加密:
在这里插入图片描述
encrypted:是加密后的公钥,只需要前端用私钥进行解密获取生成的解密数据秘钥,在根据获取的秘钥对数据进行解密就能获取所响应的数据类型
requestData:指的是加密后的数据

解密测试

    /*** 解密*/@ApiOperation(value = "解密测试")@PostMapping("/decryption")@ApiImplicitParam(name = "data",value = "数据",paramType = "query")@ResponseBodypublic Result decryption(String key,String data) throws Exception {String decryptDataOnJava = RSAUtils.decryptDataOnJava(key, privateKay);String decrypt = AesEncryptUtils.decrypt(data, decryptDataOnJava);JSONObject jsonObject =  JSON.parseObject(decrypt);String jsonData = jsonObject.getString("data");List<SysUser> dataArr = JSONArray.parseArray(jsonData,SysUser.class);System.out.println(decrypt);return Result.success().put(dataArr);}

在这里插入图片描述

总结

最后解密后是String类型的数据,输出是JSON的样子,需要JSON对数据进行转换就可以转换自己原有的数据类型,我是参考网上的案例进行使用,其中也有自己改的代码,吹水结束。


http://www.ppmy.cn/news/466561.html

相关文章

Oracle数据库中的数据加密

Oracle数据库中的数据加密 / Oracle数据库DES加密 有个需求&#xff0c;需要对某些敏感信息字段进行脱敏&#xff0c;要求在数据库中不能显示明文。如果目的侧重保护数据而非脱敏的话&#xff0c;可以考虑用表空间透明数据加密&#xff08;TDE&#xff09;&#xff0c;不过现在…

.NET(C#)常用数据加密和解密方法汇总

欢迎加入Unity业内qq交流群&#xff1a;956187480 qq扫描二维码加群 一、数据加密的概念 1、 基本概念 2、 基本功能 3、 加密形式 二、 数据加密的项目应用和学习 1、 媒体加密&#xff1a;DRM 2、 文件加密&#xff1a;文本加密、pdf、word 3、 数据加密&…

Web常见数据加密方式

MD5加密 6位和32位&#xff0c;加密密文字符串由A-Z,0-9随机分配&#xff0c;80%网站管理员或用户密码加采取MD5加密。(不可逆) SHA加密 由A-Z&#xff0c;0-9随机组合&#xff0c;SHA1,SHA256,SHA384,SHA512长度固定。(不可逆)。对于任意长度的消息&#xff0c;SHA256都会产…

数据传输过程加密方案

文章目录 前言数据加密方案数据加密细节AES加解密 RSA公钥加密总结 前言 从前一篇网络安全基础要点知识介绍中可以知道&#xff0c;在网络通信中&#xff0c;通信传输数据容易被截取或篡改&#xff0c;如果在传输用户隐私数据过程中&#xff0c;被不法分子截取或篡改&#xff…

数据加密标准(DES)概念及工作原理

0x01 数据加密标准DES介绍 数据加密标准&#xff08;Data Encryption Standard&#xff09;&#xff08;DES&#xff09;是一种用于加密数字数据的对称密钥算法。密钥长度为56位&#xff0c;安全性不强&#xff0c;但它在密码学的进步中具有很大的影响力。 0x02 数据加密标准历…

数据库数据加密及其他安全性保护

数据加密 数据加密 防止数据库中数据在存储和传输中失密的有效手段 加密的基本思想 根据一定的算法将原始数据—明文&#xff08;Plain text&#xff09;变换为不可直接识别的格式—密文&#xff08;Cipher text&#xff09; 加密方法 存储加密 传输加密 存储加密 透明…

PostgreSQL 数据加密之 pgcrypto

文章目录 pgcrypto 简介pgcrypto 安装单向加密通用哈希函数密码哈希函数 双向加密PGP 加密函数PGP 函数选项原始加密函数 随机数据函数其他事项pgcrypto 配置NULL 处理安全限制 大家好&#xff0c;我是只谈技术不剪发的 Tony 老师。 根据信息安全的相关要求&#xff0c;用户的…

漫谈数据保护和个人信息加密

相信诸位同学最近收到了不少大厂的Privacy Update类似的消息吧&#xff0c;没错&#xff0c;前两天&#xff0c;也就是25日&#xff0c;欧盟的《一般数据保护条例》(GDPR)正式生效。大厂们纷纷赶在生效日到来之前&#xff0c;匆匆更新了自己Privacy条例。很明显&#xff0c;GDP…