官网

jsencrypt :JSEncrypt

encryptlong:encryptlong - npm

前端

1,安装

1.1 安装jsencrypt,执行以下命令

npm install jsencrypt --save-dev

1.2 安装encryptlong,执行以下命令:

npm i encryptlong -S

2,创建rsa.js文件

2.1 在src/util/文件夹下创建rsa.js文件

2.2 引入‘jsencrypt’,‘encryptlong’

/* 产引入jsencrypt实现数据RSA加密 */
import JSEncrypt from 'jsencrypt' // 处理长文本数据时报错 jsencrypt.js Message too long for RSA
/* 产引入encryptlong实现数据RSA加密 */
import Encrypt from 'encryptlong' // encryptlong是基于jsencrypt扩展的长文本分段加解密功能。

2.3 准备publicKey(公钥)&& privateKey(私钥)

1、 密钥对生成地址 http://web.chacuo.net/netrsakeypair

2、Windows系统可以使用git命令行工具

  • 单击鼠标右键——git bash here 调出git bash
  • 生成私钥,密钥长度为1024bit
$ openssl genrsa -out private.pem 1024
  • 把pkcs1格式转为pkcs8格式(java侧使用的是pkcs8)

    $ openssl pkcs8 -topk8 -inform PEM -in private.pem -outform pem -nocrypt -out pkcs8.pem

    PKCS1的文件头格式 -----BEGIN RSA PRIVATE KEY-----
    PKCS8的文件头格式 -----BEGIN PRIVATE KEY-----

  • 从私钥中提取公钥
  • $ openssl rsa -in pkcs8.pem -pubout -out public.pem

2.4 写完整的加密解密函数

export default {/* JSEncrypt加密 */rsaPublicData(data) {var jsencrypt = new JSEncrypt()jsencrypt.setPublicKey(publicKey)// 如果是对象/数组的话,需要先JSON.stringify转换成字符串var result = jsencrypt.encrypt(data)return result},/* JSEncrypt解密 */rsaPrivateData(data) {var jsencrypt = new JSEncrypt()jsencrypt.setPrivateKey(privateKey)// 如果是对象/数组的话,需要先JSON.stringify转换成字符串var result = jsencrypt.encrypt(data)return result},/* 加密 */encrypt(data) {const PUBLIC_KEY = publicKeyvar encryptor = new Encrypt()encryptor.setPublicKey(PUBLIC_KEY)// 如果是对象/数组的话,需要先JSON.stringify转换成字符串const result = encryptor.encryptLong(data)return result},/* 解密 - PRIVATE_KEY - 验证 */decrypt(data) {const PRIVATE_KEY = privateKeyvar encryptor = new Encrypt()encryptor.setPrivateKey(PRIVATE_KEY)// 如果是对象/数组的话,需要先JSON.stringify转换成字符串var result = encryptor.decryptLong(data)return result}
}

2.5在main.js主文件引入,将Rsa注册为公共方法,方便其他页面调用

import Rsa from "@/utils/rsa.js"
Vue.prototype.Rsa = Rsa // 将Rsa注册为公共方法,方便其他页面调用

3,在*.vue 页面使用RSA加解密(demo)

由于已经将Rsa注册为全局公共方法,所以在需要的地方通过 this.Rsa.方法名 引入并使用就可以了,具体操作见下面demo

3.1 demo完整代码

<template><div class="rsa-container"><van-row><van-col span="24"><img src="../../assets/img/demo/rsa_banner.jpg" height="220" width="100%"/><van-field v-model="rasEncryptData.reqStr" rows="1" autosize label="加密前" type="textarea" placeholder="请输入……" @input="reqTest()"></van-field><van-field v-model="rasEncryptData.encryptStr" rows="1" autosize label="加密后" type="textarea" placeholder="请输入……" readonly></van-field><van-field v-model="rasEncryptData.decryptStr" rows="1" autosize label="解密后" type="textarea" placeholder="请输入……" readonly></van-field></van-col></van-row></div>
</template><script>
export default {data() { // 定义数据return {rasEncryptData: { // 加密后数据reqStr: '', // 加密前数据encryptStr: '', // 加密后数据decryptStr: '' // 解密后数据}}},methods: { // 定义方法reqTest() {this.rasEncryptData.encryptStr = this.Rsa.encrypt(this.rasEncryptData.reqStr) // 加密this.rasEncryptData.decryptStr = this.Rsa.decrypt(this.rasEncryptData.encryptStr) // 解密}},mounted() { // 此时已经将编译好的模板,挂载到了页面指定的容器中显示},filters: {}, // 定义私有过滤器directives: {}, // 定义私有指令components: {}, // 定义实例内部私有组件的beforeCreate() { }, // 实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性created() { }, // 实例已经在内存中创建OK,此时data和methods已经创建OK,此时还没有开始编译模板beforeMount() { }, // 此时已经完成了模板的编译,但是还没有挂载到页面中beforeUpdate() { }, // 状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点updated() { }, // 实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!beforeDestroy() { }, // 实例销毁之前调用。在这一步,实例仍然完全可用。destroyed() { } // Vue实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
}
</script>

4,前端rsa加密,后端去解密(乱码问题)

前端rsa加密,后端去解密,但是呢有中文的时候解密出来就乱了,想了各种办法未果;

结论,既然中文乱码,我就不传中文就行了哈。在加密之前用

这个方法很巧妙的利用了解决url加密的工具,何乐而不为呢。

// 前端加密前将所有中文encoder掉
// 此函数是js原生函数
var en = encodeURIComponent(str);// 后台再转换回来就行了
String result = java.net.URLDecoder.decode(en ,"UTF-8");

4.1 前端公钥私钥都保存。

 本人前端使用密钥时包含 密钥的头部 -----BEGIN PUBLIC KEY-----

后端要去掉头部。

后端

5、JAVA RSA后端加解密工具

package com.epf.gp.gp_admin.utils;import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;public class RSAUtil {// 加密数据和秘钥的编码方式public static final String UTF_8 = "UTF-8";// 填充方式public static final String RSA_ALGORITHM = "RSA/ECB/PKCS1Padding";public static final String RSA_ALGORITHM_NOPADDING = "RSA";//私钥public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMsbzWNUjDWM0mgK\n" +"RbY7yd/4+2JcsR7R1C+1BCWoeYTA9+lZtmSqQEPxj+W8YAmUw+uvNF6ZGOM3bAlt\n" +"4DCgFVaqBUCPYh3gtUjtDoNd6OhQ1hab/i7HRYq+DU5bBfm0386X/GMqCbimGkIi\n" +"T8hDxOlSjrl90D6atbfm5aXg3+m/AgMBAAECgYBI+CcU7ZYl0v7wo+ghrV88mR3v\n" +"W6/Ci834iccApINr30vxyOpPRh8qicmR1tiF+K1eqiZdahFX6FxnEtN9hLXFNhqE\n" +"Tr2L3/qChICNHJl/ZG7NDJo4vbrDzDHc6GV/OxUoUjVYOABPt/MhjCWyLg3Ywrul\n" +"+kU+ZnFlNdBtJIjquQJBAObeQ4xfATBkP9hrabgpZoedzHKA3Cj2WWBk1S1QIW/C\n" +"S3Oe1mTmzi71D2+S6XUsp1IBedkhsRh0VLaJ4m727S0CQQDhN/IHBps+DNX9PPRX\n" +"XAVejj6qRl4tPNV1YuAej2RLX7DK/qL38zhP0e3C+qVhLnevi4MZWDRghPRs6brj\n" +"dD4bAkB6ypKw0UMHovpWOGMlYVe4H9TCvgja/JPy8g50KF9wWq3Y1A2B40Scsxi/\n" +"pirneJWRx1kwhHv13sHDyLiXflwNAkEA2t8NvLo04GaFB6fXJZbuOOgwCjZ8i6YV\n" +"JBFFES31IDMMkxpHsoOR9DBlyhjf48PO2LDSZS0NKcfL6pRy5V0whQJAIcxeDmSm\n" +"CIxDd4F+CRvu4aUBvKc/vWAnwtgO+SNboqbv07AjjvDoH4henkcWECPxpDAOPKte\n" +"tB7VUhbOfBxsNA==";/*** 非对称加密,根据公钥和原始内容产生加密内容*/private static String encryptRSA(Key key, String plainText)throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException,BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, key);return Base64.encodeBase64(cipher.doFinal(plainText.getBytes(UTF_8))).toString();}/*** 根据私钥和加密内容产生原始内容*/private static String decryptRSA(Key key, String content) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, DecoderException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidAlgorithmParameterException {Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, key);byte[] contentArry = content.getBytes();return new String(cipher.doFinal(Base64.decodeBase64(contentArry)), UTF_8);}/*** 创建RSA的公钥和私钥示例 将生成的公钥和私钥用Base64编码后打印出来* @throws NoSuchAlgorithmException*/public static void createKeyPairs() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");keyPairGenerator.initialize(2048);KeyPair keyPair = keyPairGenerator.generateKeyPair();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();System.out.println("公钥"+Base64.encodeBase64(publicKey.getEncoded()));System.out.println("私钥"+Base64.encodeBase64(privateKey.getEncoded()));}/***  Description:默认的RSA解密方法 一般用来解密 参数 小数据*/public static String decryptRSADefault(String privateKeyStr,String data) {try{KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM_NOPADDING);byte[] privateKeyArray = privateKeyStr.getBytes();byte[] dataArray = data.getBytes();PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyArray));PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);Cipher cipher = Cipher.getInstance(RSA_ALGORITHM_NOPADDING);cipher.init(Cipher.DECRYPT_MODE, privateKey);return new String(cipher.doFinal(Base64.decodeBase64(dataArray)), UTF_8);}catch (Exception e){e.printStackTrace();}return "";}public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, DecoderException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, BadPaddingException, InvalidKeyException {String messageEn = "mLSTatgmYvhk8SGvny5grdYOisiYK2kX4tpnvgRL75GmP1oqjhnQa91u0Ch+/yZnclmKeu6Uid4DEkBBqeQyDj9oeZu8sEsvEHF/yIPbXFe4sKdBC5WbhDEH3TkbCrE/Y0zKQqlfdlbG9nGrbjDCts59w7e1Y/OoVtyryStedJ8=";//base64编码的私钥byte[] decoded = Base64.decodeBase64(PRIVATE_KEY);PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));String s = URLDecoder.decode(RSAUtil.decryptRSADefault(RSAUtil.PRIVATE_KEY,messageEn) ,"UTF-8");System.out.println(s);}
}

前后端解密不通过情况:

密钥对的获取:主要涉及到两个参数:秘钥格式、秘钥长度

  (1)常见秘钥格式:PKCS8(java适用)、PKCS1(其他),如果不是java平台生成的秘钥,有可能报以下错误: 

java.security.InvalidKeyException: invalid key format //秘钥格式不合法

(2)秘钥长度:1024、2048(越长越安全,效率越低),详细介绍可以参考 :https://blog.csdn.net/luoluo_onion/article/details/78354799

  注意:分段加解密时:1024的秘钥每次加密最大长度为117(128-11),长度为2048秘钥每次加解密长度为256,如果加密时设置的长度不匹配,可能会报以下错误:

javax.crypto.BadPaddingException : Decryption error //解码失败

秘钥获取的代码实现:java.security.KeyPairGenerator提供了生成秘钥的API,只需要调用即可。

public static Map<String, Object> genKeyPair() throws Exception {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);keyPairGen.initialize(1024);//2048KeyPair keyPair = keyPairGen.generateKeyPair();RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();Map<String, Object> keyMap = new HashMap<String, Object>(2);keyMap.put(PUBLIC_KEY, publicKey);keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}

3、加密实现(公钥加密)

  (1)获取Cipher需要的java.security.Key类型公钥;

  (2)调用getInstance()方法获取cipher实例,参数为填充方式(加密和解密的填充方式要统一,否则解密失败!)

  (3)使用公钥初始化cipher实例,同时设置加解密类型

  (4)对数据进行分段加密,得到字节数组。

private static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {byte[] keyBytes = Base64.decodeBase64(publicKey);X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");Key publicK = keyFactory.generatePublic(x509KeySpec);// 对数据加密Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");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 > 256) {cache = cipher.doFinal(data, offSet, 256);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * 256;}byte[] encryptedData = out.toByteArray();out.close();return encryptedData;}

4、解密实现

  (1)获取Cipher需要的java.security.Key类型私钥;

  (2)调用getInstance()方法获取cipher实例,参数为填充方式(加密和解密的填充方式要统一,否则解密失败!)

  (3)使用私钥初始化cipher实例,同时设置类型为解密类型

  (4)分段解密,得到字节数组。

private static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception {// 得到私钥  byte[] keyBytes = Base64.decodeBase64(privateKey.getBytes());PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key key = keyFactory.generatePrivate(pKCS8EncodedKeySpec);// 解密数据Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");cipher.init(Cipher.DECRYPT_MODE, key);// SealedObject obj = new SealedObject(data, cipher);int inputLen = data.length;System.out.println(data);System.out.println(inputLen);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(data, offSet, MAX_DECRYPT_BLOCK);} else {cache = cipher.doFinal(data, offSet, inputLen - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * MAX_DECRYPT_BLOCK;}byte[] decryptedData = out.toByteArray();out.close();//byte[] messageBytes = (byte[]) obj.getObject(cipher);return decryptedData;}

5\由于本人是首次接触RSA,并且对加密算法一片空白,所以过程中几乎把能遇见的错误碰了个遍,总结以下几个常见错误,引以为戒:

(1)java.security.InvalidKeyException: invalid key format

秘钥格式不合法,或者是秘钥被修改了。

java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : DerInputStream.getLength(): lengthTag=111, too big. 

    秘钥字符串主体前后有空格,或者是换行,或者有多余字段,如(-----BEGIN RSA PRIVATE KEY-----)(秘钥格式不正确)

(3)java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

    原因可能是没有使用 PKCS8(java适用)

(4)javax.crypto.BadPaddingException : Decryption error

    解密时报这个错误,很可能是填充格式不匹配,请确认加密时使用的填充格式,解密时保持统一即可,我这里使用功能的是RSA/ECB/PKCS1Padding

(5)javax.crypto.BadPaddingException: Message is larger than modulus

    解密时出现这个错误(这个错误我是羞于启齿的),可能是因为要解密的字符串中混入了什么奇怪的东西,你可以在解密前打印下要解密的字符串,再打印下转为base64后的字节数组长度(正常应该为128的倍数),否则应该是手残多加了什么东西呢。

前端参考:VUE项目使用RSA加解密(小白版)_江小白写bug的博客-CSDN博客_vue使用rsa加密

密钥生成参考:

(34条消息) 利用jsencrypt.js 进行前端RSA加密,java后端解密_tang89176的博客-CSDN博客h​​​​​​​hh​​​​​​​​​​​​​​a​​​​​​​

解密异常参考:RSA加解密的java实现(及中途的各种异常情况分析) - 聪明的娃 - 博客园

RSA前端加密,java后端解密相关推荐

  1. jsencrypt.js加密java后端解密

    文章目录 1.什么是RSA? 2.RSA算法 2.1 生成公钥和私钥 2.2 使用公钥加密信息 2.3 使用私钥解密信息 4.RSA的应用:数字签名 5.RSA的安全性 6.为什么要写这文章? 7.前 ...

  2. Java 前端加密传输后端解密以及验证码功能

    1. 加密解密 1.1 前端js加密概述 对系统安全性要求比较高,那么需要选择https协议来传输数据.当然很多情况下一般的web网站,如果安全要求不是很高的话,用http协议就可以了.在这种情况下, ...

  3. 密码的前端加密与后端解密

    一前端vue加密 #安装依赖 npm install jsencrypt#公钥加密密码 import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'const ...

  4. PHP密码问题陈婷代码_登录中利用JS前端加密PHP后端解密保证数据非明文传输的安全方法...

    为什么要研究这个呢,因为我所在单位的信息管理部门在监控系统上发现有大量的明文账号(身份证号)和密码在传输,被告知这很不安全,索性就直接解决这个问题,利用JS前端加密PHP后端再加密来解决这个问题,保证 ...

  5. 国密SM2的前端加密,后端解密(Java版本)及SM3 摘要加密

    一.简介 国密即国家密码局认定的国产密码算法.常用的主要有SM2,SM3,SM4. SM2:椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,为非对称加密,基于ECC.该算法已公开.由于该算法基于EC ...

  6. 前端加密php后端解密,使用RSA怎么实现JavaScript前端加密与PHP后端解密功能

    使用RSA怎么实现JavaScript前端加密与PHP后端解密功能 发布时间:2021-02-08 15:19:14 来源:亿速云 阅读:97 作者:Leah 这期内容当中小编将会给大家带来有关使用R ...

  7. 用户密码的加密解密操作(前端加密,后端解密)

    用户密码的加密解密操作 作者是个小菜狗,行文过程基本都基于自己理解,没有深入查阅文献,如有错误,还请大神指出 背景: 公司做的是一个某某平台的系统,包括前台和后台,作者刚毕业,刚开始试用,带我的师傅让 ...

  8. js插件jsencrypt实现rsa前端加密php后台解密

    前端页面代码 传递到php后台的是公钥加密的数据 <!DOCTYPE html> <html lang="en"> <head><meta ...

  9. RSA 前段加密 java 后台解密 已调试通过

    本人整理网上的.好多网上的调不通.在这里把调试好的贴出来. 1.   异步获取公钥(后台获取):你也可以将公钥串写在页面上: var publicKey = null; $.ajax({ url: c ...

  10. SM2国密——前端加密,后端解密(备忘)

    问题:前端提交请求时,用户名及密码到后台的过程明文传输,不安全,所以通过对账号和密码进行SM2加密后再进行提交,后台接收后再进行解密获取. SM2加密知识:https://blog.csdn.net/ ...

最新文章

  1. 入门 Python GUI 开发的第一个坑
  2. systemd系统服务管理详解
  3. Keras框架训练模型保存及载入继续训练
  4. 24. 进程同步之Lock
  5. mysql 实时聚合分析_mysql滑动聚合/年初至今聚合原理与用法实例分析
  6. 剖析boot.img的制作流程
  7. java spring流程_浅谈SpringMVC执行过程
  8. Java日历的getMinimalDaysInFirstWeek()方法和示例
  9. C# CRC16 在textbox中显示实时时间
  10. 窗体之间传递值的几种方法
  11. luogu3942将军令
  12. Python Jquery学习
  13. DVWA全级别详细通关教程
  14. java中socket学习_java的socket学习
  15. 2015中国企业500强名单
  16. 机顶盒安装APK应用的方法
  17. PPT加密了如何打开文件
  18. [读书笔记]健康还是工作,这是个问题
  19. [转]Facebook 如何管理150亿张照片
  20. sklearn.metrics.pairwise.paired_distances

热门文章

  1. 打印机多少钱一台?购买打印机打印速度快吗
  2. html中js左右图片切换效果,JS实现图片切换特效
  3. 用PyAV完成视频解码之后,如何完成视频分辨率的转换?
  4. 给交换机console接口设置密码
  5. 360c301路由器安装openwrt18.06usb打印服务器
  6. ad网络标号设置经验_ad放置网络标号
  7. gmx genion命令
  8. 【Java异常】Caused by: com.sun.mail.iap.BadCommandException: A3 BAD invalid command or parameters的解决方案
  9. 2016服务器系统配置网站,Server 2016服务器操作系统中配置NIC组合
  10. 东方财富股吧评论爬虫和情绪分析