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联调相关推荐

  1. Java实现RSA分段加密解密

    本文完成的是公钥加密,私钥解密(私钥加密公钥解密是一样的). 注意点: 秘钥生成的格式不同,使用算法也不同,公钥是X509EncodedKeySpec,私钥是PKCS8EncodedKeySpec. ...

  2. RSA加密解密及数字签名Java实现--转

    RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院 ...

  3. java rsa 117_java实现RSA非对称加密解密

    之前写过一篇java实现AES对称加密解密 在对密码加密传输的场景下 RSA非对称加密解密可能会更加适合. 原理就是后台生成一对公钥和私钥,公钥给前端用来加密,后台用私钥去解密,保证了传输过程中就算被 ...

  4. Java实现RSA 2048加密解密

    文章目录 生成RSA公钥和密钥 编写RSA加密解密类 生成RSA公钥和密钥 openssl genrsa -out rsa_private_key_2048.pem 2048 # 生成rsa私钥,X5 ...

  5. 加密解密_使用RSA密钥对加密解密数据

    使用RSA密钥对加密解密数据 作者: 郭政鸿 2021/1/6 前言: 前几天看了非对称加密, 那非对称加密处理常见的https中的应用, 平时我们可以用来做什么呢? 1. 生成RSA密钥对 使用op ...

  6. java php aes加密解密_php aes 加密解密可与java对接

    php aes 加密解密可与java对接 博主:liu1693 发表时间:2017-02-23 16:52:27 浏览量:100 class Encrypt{ //加密方法 public static ...

  7. RSA算法加密解密举例

    RSA算法加密解密举例 使用如下数字字母对照表: 明文M="its all greek to me" ,p=47,q=59,e=17,求出其密文以及给出RSA 算法加/解密过程.( ...

  8. java rsa 文件加密解密_RSA 加密、解密(自己生成加密解密文件)

    本文是自己阅读了网上的高人们的文章之后,实现功能后总结出来的,方便自己方便他人,不喜勿喷 加密解密需要生成公钥.私钥文件步骤 1.打开终端 输入 openssl 5F88AA4A-3913-4CBC- ...

  9. RSA分段加密分段解密以及密钥与.Net的转化

    代码中采用了Base64 对应的Maven仓库地址 <!-- http://mvnrepository.com/artifact/net.iharder/base64 --> <de ...

最新文章

  1. Python第三章-字符串
  2. 【量化投资】策略五(聚宽)
  3. 初等数论--同余--MILLER-RABIN素性检测算法
  4. 在Eclipse中使用JUnit4进行单元測试(0基础篇)
  5. 【转】matlab 生成调用c/c++ 代码 mex 简单实用——修改部分
  6. leetcode102
  7. matlab频响优化,MATLAB中关于频响图函数最优化的程序问题
  8. htt://3g.hn_根据我对“询问HN:谁在招聘?”的分析,开发人员技能发展趋势
  9. arp linux 清空_Linux怎么清理ARP缓存
  10. 网站前端开发基础知识学什么?必备技能
  11. Struts1.2 Hibernate Spring框架组合(二)
  12. python之celery使用详解一
  13. $_SERVER['PHP_SELF']、$_SERVER['SCRIPT_NAME'] 与 $_SERVER['REQUEST_URI']三者的区别
  14. backtrack常用的一些综合扫描工具实例用法
  15. spring自动注入bean
  16. Arduino相关函数
  17. 基于SPringBoot的玩具销售商城管理系统
  18. 【CSRF漏洞-01】跨站请求伪造漏洞靶场实战
  19. 纬地道路纵断面设计教程_市政工程这样设计!案例视频教程+CAD图纸收好,市政全覆盖...
  20. (从零开始)Cocos 3.6.0 接入微信小游戏激励广告

热门文章

  1. “幽幽远远”正式开张了,但是我的心情没有往日的开怀
  2. mysql 导出dmp文件_15款优秀的mysql管理工具与应用程序推荐
  3. pta 试试手气 C语言
  4. Qt编写可视化大屏电子看板系统26-模块4模具进度
  5. pink老师 js p85思考题
  6. jQuery——bootstrap概述
  7. 懒惰型性格分析,如何改变懒惰型性格?
  8. 获取股票实时交易数据的方法
  9. jQuery Mobel 学习相关资料整理(一)
  10. SwiftUI 音乐类App之Tuner App 调谐器适用于任何乐器支持木风 黄铜 琴弦 声音