rsa前端加密后端解密的使用

简介: rsa前端加密后端解密的使用

最近在项目中使用ras算法进行数据加密传输,加密后的数据需要存储到数据库。在使用过程中发现一个问题在windows上面每次生成的公钥和私钥是一致的,然而把代码上传到服务器(Linux系统)后每次生成的公钥和私钥就不一样了,这样造成之前加密过后的数据,后面服务器重新启动后生成不一样的公钥和私钥就没法解密之前加密过的数据了。


需要引入bcprov-jdk15on-1.55.jar包和commons-codec-1.9.jar

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.9</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.60</version>
        </dependency>

最初的代码

public class RSAEncrypt {
  /** 
   * 随机生成密钥对 
   * @throws NoSuchAlgorithmException 
   */  
  public  static Map<String,String> genKeyPair() throws NoSuchAlgorithmException {
    Map<String, String> keyMap = new HashMap<>();
    // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象  
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  
    // 初始化密钥对生成器,密钥大小为96-1024位  
    keyPairGen.initialize(1024,new SecureRandom());  
    // 生成一个密钥对,保存在keyPair中  
    KeyPair keyPair = keyPairGen.genKeyPair();
    System.out.println(keyPair.getPublic().getEncoded());
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥  
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥  
    String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
    // 得到私钥字符串  
    String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));  
    // 将公钥和私钥保存到Map
    keyMap.put("pub",publicKeyString);
    keyMap.put("pri",privateKeyString);
    return keyMap;
  }  
  /** 
   * RSA公钥加密 
   *  
   * @param str 
   *            加密字符串
   * @param publicKey 
   *            公钥 
   * @return 密文 
   * @throws Exception 
   *             加密过程中的异常信息 
   */  
  public static String encrypt( String str, String publicKey ) throws Exception{
    //base64编码的公钥
    byte[] decoded = Base64.decodeBase64(publicKey);
    RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
    //RSA加密
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
    return outStr;
  }
  /** 
   * RSA私钥解密
   *  
   * @param str 
   *            加密字符串
   * @param privateKey 
   *            私钥 
   * @return 铭文
   * @throws Exception 
   *             解密过程中的异常信息 
   */  
  public static String decrypt(String str, String privateKey) throws Exception{
    //64位解码加密后的字符串
    byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
    //base64编码的私钥
    byte[] decoded = Base64.decodeBase64(privateKey);  
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));  
    //RSA解密
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, priKey);
    String outStr = new String(cipher.doFinal(inputByte));
    return outStr;
  }
  public static void main(String[] args) throws Exception {
    //生成公钥和私钥
    Map<String, String> keyMap = genKeyPair();
    //加密字符串
    String message = "123456";
    System.out.println("随机生成的公钥为:" + keyMap.get("pub"));
    System.out.println("随机生成的私钥为:" + keyMap.get("pri"));
    String messageEn = encrypt(message,keyMap.get("pub"));
    System.out.println(message + "\t加密后的字符串为:" + messageEn);
    String messageDe = decrypt(messageEn,keyMap.get("pri"));
    System.out.println("还原后的字符串为:" + messageDe);
  }
}

这种生成的密钥对的方式由于是随机数,所以每次都是不一样的,适合前端加密完就进行解密,不需要进行存储,只是做加密传输。

keyPairGen.initialize(1024,new SecureRandom());

每次生成的密钥一致,修改

        //如果使用SecureRandom random = new SecureRandom();//windows和linux默认不同,导致两个平台生成的公钥和私钥不同
        SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
        //使用种子则生成相同的公钥和私钥
        secureRandom.setSeed("seed".getBytes());
        keyPairGenerator.initialize(1024, secureRandom);

后端解密乱码的话可以这样配置

//相同的原文、公钥能生成相同的密文。如果使用Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());//相同的原文、公钥生成的密文不同
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",new BouncyCastleProvider());

最终修改的代码,windows,linux都生成一致的密钥对

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RSAEncrypt {
  /** 
   * 随机生成密钥对 
   * @throws NoSuchAlgorithmException 
   */  
  public  static Map<String,String> genKeyPair(String seed) throws NoSuchAlgorithmException {
    Map<String, String> keyMap = new HashMap<>();
    // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象  
    KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
    SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
    //使用种子则生成相同的公钥和私钥
    secureRandom.setSeed(seed.getBytes());
    // 初始化密钥对生成器,密钥大小为96-1024位  
    keyPairGen.initialize(1024,secureRandom);
    // 生成一个密钥对,保存在keyPair中  
    KeyPair keyPair = keyPairGen.genKeyPair();
    System.out.println(keyPair.getPublic().getEncoded());
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥  
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥  
    String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
    // 得到私钥字符串  
    String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));  
    // 将公钥和私钥保存到Map
    keyMap.put("pub",publicKeyString);
    keyMap.put("pri",privateKeyString);
    return keyMap;
  }  
  /** 
   * RSA公钥加密 
   *  
   * @param str 
   *            加密字符串
   * @param publicKey 
   *            公钥 
   * @return 密文 
   * @throws Exception 
   *             加密过程中的异常信息 
   */  
  public static String encrypt( String str, String publicKey ) throws Exception{
    //base64编码的公钥
    byte[] decoded = Base64.decodeBase64(publicKey);
    RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
    //RSA加密
    //相同的原文、公钥能生成相同的密文。如果使用Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());//相同的原文、公钥生成的密文不同
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",new BouncyCastleProvider());
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
    return outStr;
  }
  /** 
   * RSA私钥解密
   *  
   * @param str 
   *            加密字符串
   * @param privateKey 
   *            私钥 
   * @return 铭文
   * @throws Exception 
   *             解密过程中的异常信息 
   */  
  public static String decrypt(String str, String privateKey) throws Exception{
    //64位解码加密后的字符串
    byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
    //base64编码的私钥
    byte[] decoded = Base64.decodeBase64(privateKey);  
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));  
    //RSA解密
    //相同的原文、公钥能生成相同的密文。如果使用Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());//相同的原文、公钥生成的密文不同
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding",new BouncyCastleProvider());
    cipher.init(Cipher.DECRYPT_MODE, priKey);
    String outStr = new String(cipher.doFinal(inputByte));
    return outStr;
  }
  public static void main(String[] args) throws Exception {
    //生成公钥和私钥
    Map<String, String> keyMap = genKeyPair("seed");
    //加密字符串
    String message = "123456";
    System.out.println("随机生成的公钥为:" + keyMap.get("pub"));
    System.out.println("随机生成的私钥为:" + keyMap.get("pri"));
    String messageEn = encrypt(message,keyMap.get("pub"));
    System.out.println(message + "\t加密后的字符串为:" + messageEn);
    String messageDe = decrypt(messageEn,keyMap.get("pri"));
    System.out.println("还原后的字符串为:" + messageDe);
  }
}

前端使用的是vue,可以npm安装至Vue项目

npm install jsencrypt --dev

页面引入jsencrypt

import { JSEncrypt } from 'jsencrypt'

公钥为后端提供,如前端需要解密数据,则也需要后端提供私钥。

methods: {
    //  加密
    encryptedData(publicKey, data) {
      // 新建JSEncrypt对象
      let encryptor = new JSEncrypt();
      // 设置公钥
      encryptor.setPublicKey(publicKey);
      // 加密数据
      return encryptor.encrypt(data);
    },
    // 解密
    decryptData(privateKey,data){
      // 新建JSEncrypt对象
      let decrypt= new JSEncrypt();
      // 设置私钥
      decrypt.setPrivateKey(privateKey);
      // 解密数据
      return decrypt.decrypt(secretWord);
    }
  }
相关文章
|
4月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
406 1
|
4月前
|
存储 消息中间件 前端开发
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
校园圈子系统校园论坛小程序采用uni-app前端框架,支持多端运行,结合PHP后端(如ThinkPHP/Laravel),实现用户认证、社交关系管理、动态发布与实时聊天功能。前端通过组件化开发和uni.request与后端交互,后端提供RESTful API处理业务逻辑并存储数据于MySQL。同时引入Redis缓存热点数据,RabbitMQ处理异步任务,优化系统性能。核心功能包括JWT身份验证、好友系统、WebSocket实时聊天及活动管理,确保高效稳定的用户体验。
245 4
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
|
5月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
373 70
|
6月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
276 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
6月前
|
前端开发 算法 NoSQL
前端uin后端php社交软件源码,快速构建属于你的交友平台
这是一款功能全面的社交软件解决方案,覆盖多种场景需求。支持即时通讯(一对一聊天、群聊、文件传输、语音/视频通话)、内容动态(发布、点赞、评论)以及红包模块(接入支付宝、微信等第三方支付)。系统采用前后端分离架构,前端基于 UniApp,后端使用 PHP 框架(如 Laravel/Symfony),配合 MySQL/Redis 和自建 Socket 服务实现高效实时通信。提供用户认证(JWT 集成)、智能匹配算法等功能,助力快速上线,显著节约开发成本。
134 2
前端uin后端php社交软件源码,快速构建属于你的交友平台
|
5月前
|
监控 前端开发 小程序
陪练,代练,护航,代打小程序源码/前端UNIAPP-VUE2.0开发 后端Thinkphp6管理/具备家政服务的综合型平台
这款APP通过技术创新,将代练、家政、娱乐社交等场景融合,打造“全能型生活服务生态圈”。以代练为切入点,提供模块化代码支持快速搭建平台,结合智能匹配与技能审核机制,拓展家政服务和商业管理功能。技术架构具备高安全性和扩展性,支持多业务复用,如押金冻结、录屏监控等功能跨领域应用。商业模式多元,包括交易抽成、增值服务及广告联名,同时设计跨领域积分体系提升用户粘性,实现生态共生与B端赋能。
425 12
|
7月前
|
监控 前端开发 Java
构建高效Java后端与前端交互的定时任务调度系统
通过以上步骤,我们构建了一个高效的Java后端与前端交互的定时任务调度系统。该系统使用Spring Boot作为后端框架,Quartz作为任务调度器,并通过前端界面实现用户交互。此系统可以应用于各种需要定时任务调度的业务场景,如数据同步、报告生成和系统监控等。
231 9
|
8月前
|
前端开发 NoSQL Java
【Java若依框架】RuoYi-Vue的前端和后端配置步骤和启动步骤
本文介绍了如何配置和启动基于Java的若依(RuoYi)项目,涵盖后端和前端的详细步骤。首先,准备Redis、MySQL以及IDE(如Idea和VS)。接着,通过GitHub获取代码并导入到IDE中,执行必要的SQL文件和配置数据库密码。然后,启动Redis并进行相关配置。最后,按照前端配置步骤克隆前端代码库,打开终端执行命令完成前端配置。整个过程详细记录了每一步的操作,帮助开发者顺利部署若依项目。 如果你觉得有帮助,请点赞、关注和收藏,这将是我持续分享的动力!
3719 4
|
7月前
|
云安全 安全 数据建模
《数字证书:互联网世界的"身份证"与"防盗门"》 ——揭秘网络安全背后的加密江湖
在2023年某深夜,上海陆家嘴金融公司机房遭遇黑客攻击,神秘青铜大门与九大掌门封印的玉牌突现,阻止了入侵。此门象征数字证书,保障网络安全。数字证书如验钞机识别假币,保护用户数据。它通过SSL/TLS加密、CA认证和非对称加密,构建安全通信。证书分为DV、OV、EV三类,分别适合不同场景。忽视证书安全可能导致巨额损失。阿里云提供一站式证书服务,助力企业部署SSL证书,迎接未来量子计算和物联网挑战。
|
9月前
|
安全 算法 网络协议
【网络原理】——图解HTTPS如何加密(通俗简单易懂)
HTTPS加密过程,明文,密文,密钥,对称加密,非对称加密,公钥和私钥,证书加密