RSA分段加密/解密 nodejs 和java联调
RSA分段加密/解密 nodejs 和java联调
文章目录
- RSA分段加密/解密 nodejs 和java联调
- 1 nodejs 环境
- 1.1 axios配置
- 1.2 API接口
- 1.3 业务
- 1.4 测试结果
- 2 JAVA 部分
- 2.0 结构目录
- 2.1 加密工具类
- 1.2 接口类
- 1.3 自定义注解
- 1.4 加密/解密业务
1 nodejs 环境
{"name": "cryptjs-test","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC","dependencies": {"axios": "^0.27.2","crypto-js": "^4.1.1","rsa-long": "^1.0.6"}
}
1.1 axios配置
const axios = require('axios');
const crypto = require('./rsa');
const service =axios.create({baseURL: "http://127.0.0.1:9010", // api的base_url process.env.BASE_API,,注意局域网访问时,不能使用localhosttimeout: 20 * 1000 // 请求超时时间
})
service.interceptors.request.use(config=>{const {headers,data,params,url} = configif(headers.rsa){headers['content-type']="application/json"config.data=crypto.encryptData(JSON.stringify(data))}return config})service.interceptors.response.use(response=>{const {headers,data} =responseconsole.log("headers", headers)console.log("data", data)if(headers.rsa){if(crypto.decryptData(data)){return JSON.parse(crypto.decryptData(data))}return null}else{return data}
})module.exports ={service
}
1.2 API接口
const request = require('../request')const rsaRequest = (data)=>{return request.service({url:'/test/info',method:'post',data,headers:{rsa:true,token:"1232323"}})
}module.exports ={rsaRequest
}
1.3 业务
const crypto = require('./rsa');const request = require('./api/rsa')request.rsaRequest({name:'张三',code:"1222323",password:"密码超级无敌"}).then(res=>{console.log(res)
})
1.4 测试结果
F:\bigdata\cryptjs-test>node test
加密后:E2FWstAzcTHGrq/leIQQ4+zha3OWD7G9MDr4cR1VcTHyqngwf3d4UcyhdN9adJ3fPgPpRk6FL3ZRI/ZcJmj3B3xZmK34jQ2btkhcSbR/ALF5fNwm6NQhzMJp7YYSX0NJrH/hvgoXqPtX6DVBHm+cDnXezS/JBn+oRRXzw7d/gg0=
headers {rsa: 'true','content-type': 'application/json','transfer-encoding': 'chunked',date: 'Mon, 22 Aug 2022 03:34:49 GMT',connection: 'close'
}
data l+gkNQMTxe5cCvirnxlaJUfG+Bbvq1xiTFVPR2clCkllrLPiHfX0J782R1sLQzNTzBs136rXCIh7Og8zy/1ksve+r9J7K8i5PIM2Vp878lDqT7sp78kG1G+hdg0v3BSpRegTP7dGnFwYGUAQMVpmMq1I1bbKAqtoHY3L5pnLFzA=
解密后:{"success":true,"code":0,"message":"user","data":{"name":"张三里斯","code":1110,"age":10,"password":"23232323"}}
解密后:{"success":true,"code":0,"message":"user","data":{"name":"张三里斯","code":1110,"age":10,"password":"23232323"}}
{success: true,code: 0,message: 'user',data: { name: '张三里斯', code: 1110, age: 10, password: '23232323' }
}F:\bigdata\cryptjs-test>
2 JAVA 部分
2.0 结构目录
2.1 加密工具类
package com.liu.mac.crypto.utils;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.junit.Test;import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;@Slf4j
public class RsaUtils {private static final String ALGORITHM = "RSA";private static final String UTF8 = StandardCharsets.UTF_8.name();// 单次加密长度最大为117private static final int MAX_ENCODE_LENGTH = 117;// 单次解密长度最大为128private static final int MAX_DECODE_LENGTH = 128;private static String publicKeyPath;private static String privateKeyPath;static {ClassLoader classLoader = RsaUtils.class.getClassLoader();publicKeyPath = classLoader.getResource("rsa.pub").getPath();privateKeyPath = classLoader.getResource("rsa.pri").getPath();log.info("publicKeyPath"+publicKeyPath);log.info("privateKeyPath"+privateKeyPath);}/*** 生成经过base64加密(公钥/私钥),并写入到文件中*/private void writeRsaKey2File()throws Exception{KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);keyPairGenerator.initialize(1024);KeyPair keyPair = keyPairGenerator.generateKeyPair();PrivateKey privateKey = keyPair.getPrivate();PublicKey publicKey = keyPair.getPublic();FileUtils.writeStringToFile(new File(publicKeyPath), Base64.encodeBase64String(publicKey.getEncoded()),UTF8);FileUtils.writeStringToFile(new File(privateKeyPath),Base64.encodeBase64String(privateKey.getEncoded()),UTF8);}/*** 从生成好的文件中获取公钥* 公钥和私钥保存在文件中是使用base64的方式进行编码的,所以第一步需要进行base64解码* 公钥使用规则 X509EncodedKeySpec* 私钥使用规则 PKCS8EncodedKeySpec* @return*/public PublicKey getPublicKey()throws Exception{String endcodeBase64 = FileUtils.readFileToString(new File(publicKeyPath), UTF8);log.info("base64-public: "+endcodeBase64);byte[] publicKeyBytes = Base64.decodeBase64(endcodeBase64);KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
// 公钥使用规则x509X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);return keyFactory.generatePublic(x509EncodedKeySpec);}/*** 从生成好的文件中获取私钥* 公钥和私钥保存在文件中是使用base64的方式进行编码的,所以第一步需要进行base64解码* 公钥使用规则x509* 私钥使用规则 PKCS8EncodedKeySpec* @return*/public PrivateKey getPrivateKey()throws Exception{String endcodeBase64 = FileUtils.readFileToString(new File(privateKeyPath), UTF8);log.info("base64-private :"+endcodeBase64);byte[] privateKeyBytes = Base64.decodeBase64(endcodeBase64);KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
// 私钥使用规则 PKCS8EncodedKeySpecPKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);return keyFactory.generatePrivate(pkcs8EncodedKeySpec);}@Testpublic void test1()throws Exception{
// 生成秘钥对 生成一次后保存下来,不要乱折腾
// writeRsaKey2File();
// String text = "搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;搜晚上我是超人,我怕谁12132l;";
// System.out.println(" ------------------公钥加密,私钥解密-------------------------------");
// String encryptStr = encrypt(text, getPublicKey());
// System.out.println(encryptStr);
// String decryptStr = decrypt(encryptStr, getPrivateKey());
// System.out.println(decryptStr);
// System.out.println(" ------------------私钥加密,公钥解密-------------------------------");
//
// encryptStr = encrypt(text,getPrivateKey());
// System.out.println(encryptStr);
// decryptStr = decrypt(encryptStr,getPublicKey());
// System.out.println(decryptStr);// String encStr ="kfozuRxvT3qZZaJb02FpAD/fBJcd7ZFbH7olyDo9M2Xz3tnSZYSsuluTFPFN+7QyBncWslzWioFiEZ1g8Gg7qKrnykikmPhUbFwPrEjg1KTIkGc8LwwflKV2YdBBjg1Utud+C753Nn4ryxfQq0HaVOVUO8ae8UFEziRxRWmWLB0=";
//
// String decryptStr = decrypt(encStr,getPrivateKey());
// System.out.println(decryptStr);
// String aa ="{\"success\":true,\"code\":0,\"message\":\"user\",\"data\":{\"name\":\"张三里斯\",\"code\":1110,\"age\":10,\"password\":\"23232323\"}}";
//
// String decryptStr = encrypt(aa,getPrivateKey());
// System.out.println(decryptStr);
//
// String encryptStr = decrypt(decryptStr,getPublicKey());
// System.out.println(encryptStr);String data = "X8QzF0qV3++7peAgC71YfpVSiOP16W+IPa18uHz2WPzMk++u1uVPSkgXIwxMoSk55wq7/iqspWkG1EUU78Xx8qeKWQbJA2e2R47PNKhLeXNoF/7Gr1r9ptMHJTRRiCwZJbfesyRk7MoeRIpb7N2iig63RETW22kKS483/J0YaXA=";String encryptStr = decrypt(data,getPublicKey());System.out.println(encryptStr);}/*** 加密类* @param originalContent 要加密的明文* @param key 公钥或者私钥* @return Base64 加密后的字符串*/public byte [] encryptByte(String originalContent, Key key) throws Exception{Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE,key);byte [] bytes = doCodec(cipher,originalContent.getBytes(UTF8),MAX_ENCODE_LENGTH);return bytes;}/*** 加密类* @param originalContent 要加密的明文* @param key 公钥或者私钥* @return Base64 加密后的字符串*/public String encrypt(String originalContent, Key key) throws Exception{Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE,key);byte [] bytes = doCodec(cipher,originalContent.getBytes(UTF8),MAX_ENCODE_LENGTH);return Base64.encodeBase64String(bytes);}/*** 解密类* @param base64EncodeContent base64加密后的密文* @param key 公钥或者私钥* @return 原始内容*/private String decrypt(String base64EncodeContent, Key key) throws Exception{byte[] decodeBase64 = Base64.decodeBase64(base64EncodeContent);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE,key);byte [] bytes = doCodec(cipher,decodeBase64,MAX_DECODE_LENGTH);return new String(bytes,UTF8);}/*** 解密类* @param base64EncodeContent base64加密后的密文* @param key 公钥或者私钥* @return 原始内容*/public byte[] decryptByte(String base64EncodeContent, Key key) throws Exception{byte[] decodeBase64 = Base64.decodeBase64(base64EncodeContent);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE,key);byte [] bytes = doCodec(cipher,decodeBase64,MAX_DECODE_LENGTH);return bytes;}/*** 加密/解密的公共方法* @param cipher 加密或者解密* @param bytes 明文/密文* @param maxBlockSize 处理的最大长度* @return 返回密文或者明文* @throws Exception*/private byte[] doCodec(Cipher cipher, byte[] bytes, int maxBlockSize) throws Exception{
// 偏移量int offset = 0;// 循环成次数int count = 0 ;
// 加密/解密后的结果byte [] temp;
// 加密/解密的总结果ByteArrayOutputStream bos = new ByteArrayOutputStream();// 输入的字符串长度int inputLength = bytes.length;while ((inputLength - offset)>0){if((inputLength - offset)>maxBlockSize){temp = cipher.doFinal(bytes,offset,maxBlockSize);}else {temp = cipher.doFinal(bytes,offset,inputLength - offset);}bos.write(temp,0,temp.length);count ++;offset = maxBlockSize*count;}byte[] result = bos.toByteArray();bos.close();return result;}}
1.2 接口类
package com.liu.mac.crypto.controller;import com.liu.mac.crypto.aop.HttpBodyDecrypt;
import com.liu.mac.crypto.entity.User;
import com.liu.mac.crypto.utils.ResultVO;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/test")
public class CryptoController {@HttpBodyDecrypt@PostMapping("/info")public ResultVO<User> restest(@RequestBody User user){System.out.println("user"+user);User user1 = new User();user.setCode(1110);user.setName("张三里斯");user.setPassword("23232323");user.setAge(10);return ResultVO.ok("user",user);}}
1.3 自定义注解
package com.liu.mac.crypto.aop;import java.lang.annotation.*;/*** 定义注解* 功能:排除请求体/响应体解密/加密,请求体参数/响应不需要进行解密/加密*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcludeHttpBodyDecrypt {
}
package com.liu.mac.crypto.aop;import java.lang.annotation.*;/*** 定义注解* 功能:请求体/响应体解密/加密,请求体参数/响应需要进行解密/加密*/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HttpBodyDecrypt {
}
1.4 加密/解密业务
package com.liu.mac.crypto.advice;import com.liu.mac.crypto.aop.ExcludeHttpBodyDecrypt;
import com.liu.mac.crypto.aop.HttpBodyDecrypt;
import com.liu.mac.crypto.utils.RsaUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.Charset;@ControllerAdvice
@Slf4j
public class RequestBodyHandler implements RequestBodyAdvice {@AutowiredRsaUtils rsaUtils;@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {//排除解密注解boolean methodHasExcludeHttpBodyDecrypt = methodParameter.hasMethodAnnotation(ExcludeHttpBodyDecrypt.class);if (methodHasExcludeHttpBodyDecrypt) {return false;}//解密注解boolean methodHasHttpBodyDecrypt = methodParameter.hasMethodAnnotation(HttpBodyDecrypt.class);if (methodHasHttpBodyDecrypt) {return true;}boolean classHasExcludeHttpBodyDecrypt = methodParameter.getDeclaringClass().getAnnotation(ExcludeHttpBodyDecrypt.class) != null;if (classHasExcludeHttpBodyDecrypt) {return false;}boolean classHasHttpBodyDecrypt = methodParameter.getDeclaringClass().getAnnotation(HttpBodyDecrypt.class) != null;if (classHasHttpBodyDecrypt) {return true;}return false;}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {System.out.println("beforeBodyRead");if (inputMessage.getBody().available()<=0) {return inputMessage;}byte[] requestDataByte=new byte[inputMessage.getBody().available()];inputMessage.getBody().read(requestDataByte);byte[] requestDataByteNew=null;try {// 解密requestDataByteNew = rsaUtils.decryptByte(new String(requestDataByte,"UTF-8"), rsaUtils.getPrivateKey());} catch (Exception e) {e.printStackTrace();}// 使用解密后的数据,构造新的读取流InputStream rawInputStream = new ByteArrayInputStream(requestDataByteNew);return new HttpInputMessage() {@Overridepublic HttpHeaders getHeaders() {return inputMessage.getHeaders();}@Overridepublic InputStream getBody() throws IOException {return rawInputStream;}};
// return inputMessage;}@Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {System.out.println("afterBodyRead");log.info("请求体为]"+body);return body;}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {return body;}}
package com.liu.mac.crypto.advice;import cn.hutool.json.JSONUtil;
import com.liu.mac.crypto.aop.ExcludeHttpBodyDecrypt;
import com.liu.mac.crypto.aop.HttpBodyDecrypt;
import com.liu.mac.crypto.utils.RsaUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;@RestControllerAdvice
public class ResponseBodyHandler implements ResponseBodyAdvice {@AutowiredRsaUtils rsaUtils;@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {//排除解密注解boolean methodHasExcludeHttpBodyDecrypt = returnType.hasMethodAnnotation(ExcludeHttpBodyDecrypt.class);if (methodHasExcludeHttpBodyDecrypt) {return false;}//解密注解boolean methodHasHttpBodyDecrypt = returnType.hasMethodAnnotation(HttpBodyDecrypt.class);if (methodHasHttpBodyDecrypt) {return true;}boolean classHasExcludeHttpBodyDecrypt = returnType.getDeclaringClass().getAnnotation(ExcludeHttpBodyDecrypt.class) != null;if (classHasExcludeHttpBodyDecrypt) {return false;}boolean classHasHttpBodyDecrypt = returnType.getDeclaringClass().getAnnotation(HttpBodyDecrypt.class) != null;if (classHasHttpBodyDecrypt) {return true;}return false;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {String content = JSONUtil.toJsonStr(body);System.out.println(content);response.getHeaders().set("rsa","true");String result = null;try {result = rsaUtils.encrypt(content,rsaUtils.getPublicKey());System.out.println("返回后加密串为"+result);} catch (Exception e) {e.printStackTrace();}return result;}
}
RSA分段加密/解密 nodejs 和java联调相关推荐
- Java实现RSA分段加密解密
本文完成的是公钥加密,私钥解密(私钥加密公钥解密是一样的). 注意点: 秘钥生成的格式不同,使用算法也不同,公钥是X509EncodedKeySpec,私钥是PKCS8EncodedKeySpec. ...
- RSA加密解密及数字签名Java实现--转
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院 ...
- java rsa 117_java实现RSA非对称加密解密
之前写过一篇java实现AES对称加密解密 在对密码加密传输的场景下 RSA非对称加密解密可能会更加适合. 原理就是后台生成一对公钥和私钥,公钥给前端用来加密,后台用私钥去解密,保证了传输过程中就算被 ...
- Java实现RSA 2048加密解密
文章目录 生成RSA公钥和密钥 编写RSA加密解密类 生成RSA公钥和密钥 openssl genrsa -out rsa_private_key_2048.pem 2048 # 生成rsa私钥,X5 ...
- 加密解密_使用RSA密钥对加密解密数据
使用RSA密钥对加密解密数据 作者: 郭政鸿 2021/1/6 前言: 前几天看了非对称加密, 那非对称加密处理常见的https中的应用, 平时我们可以用来做什么呢? 1. 生成RSA密钥对 使用op ...
- java php aes加密解密_php aes 加密解密可与java对接
php aes 加密解密可与java对接 博主:liu1693 发表时间:2017-02-23 16:52:27 浏览量:100 class Encrypt{ //加密方法 public static ...
- RSA算法加密解密举例
RSA算法加密解密举例 使用如下数字字母对照表: 明文M="its all greek to me" ,p=47,q=59,e=17,求出其密文以及给出RSA 算法加/解密过程.( ...
- java rsa 文件加密解密_RSA 加密、解密(自己生成加密解密文件)
本文是自己阅读了网上的高人们的文章之后,实现功能后总结出来的,方便自己方便他人,不喜勿喷 加密解密需要生成公钥.私钥文件步骤 1.打开终端 输入 openssl 5F88AA4A-3913-4CBC- ...
- RSA分段加密分段解密以及密钥与.Net的转化
代码中采用了Base64 对应的Maven仓库地址 <!-- http://mvnrepository.com/artifact/net.iharder/base64 --> <de ...
最新文章
- Python第三章-字符串
- 【量化投资】策略五(聚宽)
- 初等数论--同余--MILLER-RABIN素性检测算法
- 在Eclipse中使用JUnit4进行单元測试(0基础篇)
- 【转】matlab 生成调用c/c++ 代码 mex 简单实用——修改部分
- leetcode102
- matlab频响优化,MATLAB中关于频响图函数最优化的程序问题
- htt://3g.hn_根据我对“询问HN:谁在招聘?”的分析,开发人员技能发展趋势
- arp linux 清空_Linux怎么清理ARP缓存
- 网站前端开发基础知识学什么?必备技能
- Struts1.2 Hibernate Spring框架组合(二)
- python之celery使用详解一
- $_SERVER['PHP_SELF']、$_SERVER['SCRIPT_NAME'] 与 $_SERVER['REQUEST_URI']三者的区别
- backtrack常用的一些综合扫描工具实例用法
- spring自动注入bean
- Arduino相关函数
- 基于SPringBoot的玩具销售商城管理系统
- 【CSRF漏洞-01】跨站请求伪造漏洞靶场实战
- 纬地道路纵断面设计教程_市政工程这样设计!案例视频教程+CAD图纸收好,市政全覆盖...
- (从零开始)Cocos 3.6.0 接入微信小游戏激励广告