RSA有两个密钥,一个是公开的,称为公开密钥;一个是私密的,称为私密密钥。

特点:

  • 公开密钥是对大众公开的,私密密钥是服务器私有的,两者不能互推得出。
  • 用公开密钥对数据进行加密,私密密钥可解密;私密密钥对数据加密,公开密钥可解密。
  • 速度较对称加密慢。
RSA使用场景

第一个场景:战场上,B要给A传递一条消息,内容为某一指令。

RSA的加密过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A传递自己的公钥给B,B用A的公钥对消息进行加密。

(3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。

在这个过程中,只有2次传递过程,第一次是A传递公钥给B,第二次是B传递加密消息给A,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行解密,防止了消息内容的泄露。

第二个场景:A收到B发的消息后,需要进行回复“收到”。

RSA签名的过程如下:

(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。

(2)A用自己的私钥对消息加签,形成签名,并将加签的消息和消息本身一起传递给B。

(3)B收到消息后,在获取A的公钥进行验签,如果验签出来的内容与消息本身一致,证明消息是A回复的。

在这个过程中,只有2次传递过程,第一次是A传递加签的消息和消息本身给B,第二次是B获取A的公钥,即使都被敌方截获,也没有危险性,因为只有A的私钥才能对消息进行签名,即使知道了消息内容,也无法伪造带签名的回复给B,防止了消息内容的篡改。

但是,综合两个场景你会发现,第一个场景虽然被截获的消息没有泄露,但是可以利用截获的公钥,将假指令进行加密,然后传递给A。第二个场景虽然截获的消息不能被篡改,但是消息的内容可以利用公钥验签来获得,并不能防止泄露。所以在实际应用中,要根据情况使用,也可以同时使用加密和签名,比如A和B都有一套自己的公钥和私钥,当A要给B发送消息时,先用B的公钥对消息加密,再对加密的消息使用A的私钥加签名,达到既不泄露也不被篡改,更能保证消息的安全性。

加密:

一般来说,我们通过公开密钥对信息加密,然后发送给服务端,服务端再用私密密钥解密,获取保密的信息。(而RSA中通过私密密钥加密,然后通过公开密钥正确地解密获取信息,但这个过程对于加密来说没有意义,因为公开密钥是公开的,也就是说大家都可以解密。所以私密密钥加密、公开密钥解密用于签名功能)

签名:

签名的目的在于证明给大伙看这份信息是本人所发,并且发送过程中没被篡改。

服务端对于将要发送的信息进行摘要操作(比如SHA1),然后对其摘要值用私密密钥加密,形成签名值,将发送的信息与签名值发送出去。客户端收到信息和签名值后,用公开密钥将签名值解密,然后将信息进行摘要操作,再比对两者的摘要值,就可知该信息是否服务端所发,发送过程是否有篡改。

联调阶段,走过的坑说明:

// 注意:加密密文与签名都是唯一的,不会变化。
// 注意:vue 端密钥都要带pem格式。java 不要带pem格式
// 注意:vue端及java端函数参数、返回值要求是什么类型及何进制。搞明白哪里用base64,哪里2进制,哪里16进制。
// 重点还是要了解点原理,比如sha1withrsa,先经过sha1算法,知道aaa,哈希后的密文16进制是:7e240de74fb1ed08fa08d38063f6a6a91462a815,对比自己的程序有没有算错。
// 利用一些在线测试工具帮忙验证自己的程序过程。http://www.metools.info/code/c82.html ; 同时知道如何查引入的类库各api的官网,了解如何使用各函数。
// 不然遇到莫名奇妙的错误无从解决。报错的地方不一定是程序实际错误的地方。了解查错的方式有:打庄、debug.

不多解释了,直接上源码

服务器端java:

工具类,rsa加解密,RsaUtil.java

package com.ruoyi.common.utils.enDeCrypt;import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.UtilException;import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.util.Base64;
import javax.crypto.Cipher;
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;import static io.netty.util.CharsetUtil.UTF_8;/** 加密和解密花费时间长、速度慢,故使用RSA只能加密少量数据,大量的数据加密还要靠对称密码算法。* 第一种用法是公钥加密、私钥解密——用于加密;第二种是私钥签名、公钥验签——用于签名* @author EvianZou*/
public class RsaUtil {/*** 密钥长度与原文长度对应,越长速度越慢* 1024bit 密钥 能加密明文最大的长度是 1024/8 -11 = 117 byte* 2048bit 密钥 能加密明文最大的长度是 2048/8 -11 = 245 byte*/private final static int KEY_SIZE = 1024;/** RSA算法 RSA-1024位 RSA2-2048位*/private final static String ALGORITHM = "RSA";//java默认"RSA"="RSA/ECB/PKCS1Padding"private final static String PADDING_MODE = "RSA/ECB/PKCS1Padding";/** 签名算法* RSA: 常用 SHA1WithRSA,有 MD2withRSA、MD5withRSA、SHA1withRSA;* RSA2:  常用:SHA256WithRSA,有 SHA224withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA 、RIPEMD128withRSA、RIPEMD160withRSA;*/public static final String SIGN_ALGORITHM = "SHA1withRSA";/** 字符编码*/private final static String ENCODING = "UTF-8";/** RSA最大加密明文大小* RSA:117* RSA2:245*/private static final int MAX_ENCRYPT_BLOCK = 117;/** RSA最大解密密文大小* RSA:128* RSA2:256*/private static final int MAX_DECRYPT_BLOCK = 128;public Map<String, String> getKeyMap() {return keyMap;}public void setKeyMap(Map<String, String> keyMap) {this.keyMap = keyMap;}/*** 用于封装随机产生的公钥与私钥*/private Map<String, String> keyMap;public RsaUtil(boolean isKeyBase64) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchProviderException {setKeyMap(generateKeyPair(isKeyBase64));}/*** 随机生成密钥对* @param isKeyBase64 密钥base64加密为true,hex为false*/private Map<String, String> generateKeyPair(boolean isKeyBase64) throws NoSuchAlgorithmException, UnsupportedEncodingException, NoSuchProviderException {// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);// 初始化密钥对生成器keyPairGen.initialize(KEY_SIZE, new SecureRandom());// 生成一个密钥对,保存在keyPair中KeyPair keyPair = keyPairGen.generateKeyPair();// 得到私钥RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();// 得到公钥RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();String publicKeyString = isKeyBase64 ? Base64.getEncoder().encodeToString(publicKey.getEncoded()) : Convert.bytesToHex(publicKey.getEncoded());// 得到私钥字符串String privateKeyString = isKeyBase64 ? Base64.getEncoder().encodeToString(privateKey.getEncoded()) : Convert.bytesToHex(privateKey.getEncoded());// 将公钥和私钥保存到MapMap<String, String> map = new HashMap<>(32);//表示公钥map.put("publicKey", publicKeyString);//表示私钥map.put("privateKey", privateKeyString);return map;}/*** 流程1:RSA公钥加密,再BASE64加密,再base64解密,再RSA私钥解密* 流程2:RSA私钥加密,再BASE64加密,再base64解密,再RSA公钥解密** @param text        加密字符串/解密字符串* @param secretKey   加密秘钥* @param isPublicKey 公钥/私钥* @param isEncrypt   加密/解密* @param isKeyBase64 密钥base64加密为true,hex为false* @param isTextBase64 密文base64加密为true,hex为false* @param isUrlCode 密文urlencode为true,否则为false* @return 密文/明文* @throws Exception 加密过程中的异常信息*/private String enDecrypt(String text, String secretKey, boolean isPublicKey, boolean isEncrypt, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {//base64编码的秘钥byte[] decodedKey = isKeyBase64 ? Base64.getDecoder().decode(secretKey.getBytes(ENCODING)) : Convert.hexToByteArray(secretKey);byte[] decodeText;int encodeMode = 0;int max_block = 0;int textLength = 0;Cipher cipher = Cipher.getInstance(PADDING_MODE);UrlCode urlCode = new UrlCode();if (isEncrypt) {encodeMode = Cipher.ENCRYPT_MODE;max_block = MAX_ENCRYPT_BLOCK;//待加密字符串decodeText = text.getBytes(ENCODING);textLength = text.getBytes(ENCODING).length;} else {encodeMode = Cipher.DECRYPT_MODE;max_block = MAX_DECRYPT_BLOCK;decodeText = isUrlCode ? urlCode.decodeURL(text, UTF_8).getBytes(ENCODING) : text.getBytes(ENCODING);// 注意:byte[]转String,不能 byte[].toString(); 可用new String(byte[])decodeText = isTextBase64 ? Base64.getDecoder().decode(decodeText) : Convert.hexToByteArray(new String(decodeText, ENCODING));textLength = decodeText.length;}if (isPublicKey) {cipher.init(encodeMode, (RSAPublicKey) KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(decodedKey)));} else {cipher.init(encodeMode, (RSAPrivateKey) KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(decodedKey)));}ByteArrayOutputStream out = new ByteArrayOutputStream();int offSet = 0;byte[] cache;int i = 0;// 对数据分段加密while (textLength - offSet > 0) {if (textLength - offSet > max_block) {cache = cipher.doFinal(decodeText, offSet, max_block);} else {cache = cipher.doFinal(decodeText, offSet, textLength - offSet);}out.write(cache, 0, cache.length);i++;offSet = i * max_block;}byte[] byteText = out.toByteArray();out.close();String resultText = out.toString();if (isEncrypt) {resultText = isTextBase64 ? Base64.getEncoder().encodeToString(byteText) : Convert.bytesToHex(byteText);resultText = isUrlCode ? urlCode.encodeURL(resultText, UTF_8) : resultText;}return resultText;}public String encryptByPublicKey(String plainText, String publicKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {return enDecrypt(plainText, publicKey, true, true, isKeyBase64, isTextBase64, isUrlCode);}public String decryptByPrivateKey(String cipherText, String privateKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {return enDecrypt(cipherText, privateKey, false, false, isKeyBase64, isTextBase64, isUrlCode);}/*** RSA签名** @param signText   待签名数据* @param privateKey 私钥* @param isKeyBase64 密钥base64加密为true,hex为false* @param isTextBase64 密文base64加密为true,hex为false* @param isUrlCode 密文urlencode为true,否则为false* @return 签名值*/public String signByPrivateKey(String signText, String privateKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {try {KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);byte[] decodeKey = isKeyBase64 ? Base64.getDecoder().decode(privateKey) : Convert.hexToByteArray(privateKey);PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(decodeKey);//DER input, Integer tag error ,原因密钥错误PrivateKey private_key = (RSAPrivateKey) keyFactory.generatePrivate(privateKeySpec);Signature signature = Signature.getInstance(SIGN_ALGORITHM);signature.initSign(private_key);String  sign_text = isTextBase64?Convert.bytesToHexString(Base64.getDecoder().decode(signText.getBytes(ENCODING))):signText;//  System.out.println("服务器端:待签名数据:"+sign_text);assert sign_text != null;byte[] digestText = genDigest(sign_text,SIGN_ALGORITHM );// 生成消息摘要 因客户端签名时参数为16进制, 可以通过加密算法验证是否正确signature.update(Convert.bytesToHexString(digestText).getBytes(ENCODING));// System.out.println("服务器端:摘要数据:"+new String(digestText));byte[] signedByte = signature.sign();// System.out.println("服务器端:签名数据:"+Convert.bytesToHexString(signedByte));UrlCode urlCode = new UrlCode();String signedText = isTextBase64 ? Base64.getEncoder().encodeToString(signedByte) : Convert.bytesToHex(signedByte);signedText = isUrlCode ? urlCode.encodeURL(signedText, UTF_8) : signedText;return signedText;} catch (Exception e) {throw new UtilException(e.getMessage());}}/** 生成消息摘要*/public byte[] genDigest(String plainText, String algorithm) throws NoSuchAlgorithmException, UnsupportedEncodingException {MessageDigest messageDigest = MessageDigest.getInstance(algorithm.split("w")[0]);//  System.out.println("服务器端,哈希算法:"+algorithm.split("w")[0]);byte []  digestText = messageDigest.digest(plainText.getBytes(ENCODING));// System.out.println("服务器端,摘要:"+bytesToHexString(digestText));return digestText;}/*** RSA验签名检查** @param signText   待签名数据* @param signedText 已签名数据* @param publicKey  公钥* @param isKeyBase64 密钥base64加密为true,hex为false* @param isTextBase64 密文base64加密为true,hex为false* @param isUrlCode 密文urlencode为true,否则为false* @return 布尔值*/public boolean verifySignPublicKey(String signText, String signedText, String publicKey, boolean isKeyBase64, boolean isTextBase64, boolean isUrlCode) throws Exception {boolean isVerified;try {KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);byte[] decodedKey = isKeyBase64 ? Base64.getDecoder().decode(publicKey) : Convert.hexToByteArray(publicKey);PublicKey pubKey = (RSAPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));Signature signature = Signature.getInstance(SIGN_ALGORITHM);signature.initVerify(pubKey);signText = isTextBase64?Convert.bytesToHexString( Base64.getDecoder().decode(signText.getBytes(ENCODING))) :signText;// 生成消息摘要assert signText != null;// System.out.println("验证,待签名数据:"+signText);byte[] digestText = genDigest(signText,SIGN_ALGORITHM );// 生成消息摘要signature.update(Convert.bytesToHexString(digestText).getBytes(ENCODING));UrlCode urlCode = new UrlCode();String decodeText = isUrlCode ? urlCode.decodeURL(signedText, UTF_8) : signedText;byte[] bytesText = isTextBase64 ? Base64.getDecoder().decode(decodeText) : Convert.hexToByteArray(decodeText);//DER input, Integer tag error ,或 DerInputStream.getLength(): lengthTag=111, too big.原因密钥错误isVerified = signature.verify(bytesText);} catch (Exception e) {throw new UtilException(e.getMessage());}return isVerified;}// PKCS#1 与PKCS#8 格式转换// 带头和尾的密钥,去掉头和尾后,再按指定格式增加头和尾public Map<String,String> convertKeyFormat(Map<String,String> mapSource,String keyMode){Map<String,String> map = removeHeaderAndBottom(mapSource,keyMode);map = formatKey (map,keyMode);return map;}public Map<String,String>   removeHeaderAndBottom (Map<String,String> mapSource,String keyMode){Map<String,String> map = new HashMap<>();Map<String,String> mapHeaderAndBottom_publicKey = genKeyHeaderAndBottom(keyMode,false);Map<String,String> mapHeaderAndBottom_privateKey  = genKeyHeaderAndBottom(keyMode,true);String privateKey = mapSource.get("privateKey");String publicKey =  mapSource.get("publicKey");publicKey =  publicKey.replaceAll(mapHeaderAndBottom_publicKey.get("header"),"");publicKey = publicKey.replaceAll(mapHeaderAndBottom_publicKey.get("bottom"),"");privateKey=privateKey.replaceAll(mapHeaderAndBottom_privateKey.get("header"),"");privateKey= privateKey.replaceAll(mapHeaderAndBottom_privateKey.get("bottom"),"");map.put("publicKey",publicKey);map.put("privateKey",privateKey);return map;}// 不带头和尾的密钥,按指定格式增加头和尾public  Map<String,String> formatKey( Map<String,String> mapSource, String keyMode){Map<String,String> map = new HashMap<>();map.put("publicKey", formatKey(mapSource.get("publicKey"),keyMode,false));map.put("privateKey", formatKey(mapSource.get("privateKey"),keyMode,true));return map;}// 格式化key,增加头和尾private  String formatKey( String  keyBody, String keyMode,boolean isPrivateKey ){Map<String,String> map = genKeyHeaderAndBottom(keyMode,isPrivateKey);String keyHeader = map.get("header");String keyBottom =map.get("bottom");String  strKey = keyHeader + "\n";int nPrivateKeyLen = keyBody.length();char[] status = keyBody.toCharArray();for(int i = 64; i < nPrivateKeyLen; i+=64){if(status[i] != '\n'){status[i]= '\n';}i++;}strKey += String.valueOf(status);strKey += "\n";strKey += keyBottom;strKey += "\n";return strKey;}// 按指定格式生成头和尾public Map<String,String> genKeyHeaderAndBottom(String keyMode,boolean isPrivateKey){Map<String,String> map = new HashMap<>();if (keyMode == "PKCS#1") {if (isPrivateKey) {map.put("header", "-----BEGIN RSA PRIVATE KEY-----");} else {map.put("header", "-----BEGIN RSA PUBLIC KEY-----");}if (isPrivateKey) {map.put("bottom", "-----END RSA PRIVATE KEY-----");} else {map.put("bottom", "-----END RSA PUBLIC KEY-----");}}else if (keyMode == "PKCS#8") {if (isPrivateKey) {map.put("header", "-----BEGIN PRIVATE KEY-----");} else {map.put("header", "-----BEGIN PUBLIC KEY-----");}if (isPrivateKey) {map.put("bottom", "-----END PRIVATE KEY-----");} else {map.put("bottom", "-----END PUBLIC KEY-----");}}return map;}
}

测试使用流程方法

  public static void testRSAflow() throws Exception {// 测试前后端使用流程// 1、后端生成密钥对,公钥分享给前端,前端获取到服务器给的公钥。// 2、前端用服务器端给的公钥 及算法:RSA/CBC/PKCS1Padding 加密"xhy 我爱你 中国 依芸Yiyun !!!" 生成加密数据。// 3、前端然后生成自己的密钥对,用自己的私钥及算法SHA1withRSA生成摘要签名。// 4、前端把加密数据、自己的公钥与签名一并发给后端。// 3、后端收到加密数据、签名数据、前端的公钥,先用前端公钥、签名数据、算法SHA1withRSA 验签,验签通过后再用后端的私钥、算法:RSA/CBC/PKCS7Padding 解密数据。// 注意:密钥与密文全部base64编码RsaUtil rsaUtil = new RsaUtil(true);String  privateKey_s = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIfKRPRzS0a9Rg1LQizkfIL1ciAMEFs45tl49ERuwIA1kcUrtB1Cjj3bKMLO0Sp7992ECOWVZsE6DZPle3kVYFufIBT4pjR1oJqRs4Z9g5bkwY6p743eGnT1pxri5LNqBdevlKsjqwcfIdOhIqz2BaeM3PT1O52PI9e+U40XEri7AgMBAAECgYAmNYNLqbmP0SiKCxg226AxlXEklWBw2sUSgpdxPhzKtsgqzA5lgVnXC/kfP+TZaIKpgUKjn3OHgZdae2NQAfTXxTcvhNGYSOeJ8VgslQueoJW7ypgQ/IoNy2DeglObAJ3uCgA4F566j6H7IvcllKGmDT/6PUlljxZJpBMfslspgQJBAP19EMRxmV4vYL7o55oR397UEUXn3vO88SPo2gxaPZ/ltzgaHM5R1zALPE1EfPIPqVdGf2hcowr22pC1BG+nlXsCQQCJIq4USfgNmjGwquo5PyksQ9vsYc/OxGBxEqTpVez24eJb7tvoqvbYfpleeEyWgtvzHqnlY24QdONhVVm5zOXBAkAxt7PwM6+3D2fUSe4TA+p60/FHWsEZ4TcSqfsKbTClCfMzp7t6pAamv61mIka3W2cFXShkGbdI0T3xH+/szlu9AkBi3SSgrd7td39hPSaU1MsLBXT0SmO1Te+1NNq8+VxXc+trmZzidPZ2h3ZsG9AjJf4JnM6g9/iuVoZiclS4VVZBAkEAsPkIGRvX4Nj3ljiBjgdJ68JRZC3gK/kXLNeefIeHg6F/4eyg729PlfdD2mvPb8hiszvsT1zvF8gvxGi4lT6B/w==" ;String  publicKey_s = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHykT0c0tGvUYNS0Is5HyC9XIgDBBbOObZePREbsCANZHFK7QdQo492yjCztEqe/fdhAjllWbBOg2T5Xt5FWBbnyAU+KY0daCakbOGfYOW5MGOqe+N3hp09aca4uSzagXXr5SrI6sHHyHToSKs9gWnjNz09TudjyPXvlONFxK4uwIDAQAB";String  publicKey_c ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQPgskvyi9D/IuD0x73M2UOxBH3daAGbxLfUiSraG3cEgZCp7/o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHvvVgddaCvaFZkcIno4EVtHCLldKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9iFi2KDWwF30e2PHRpRQIDAQAB";// publicKey_s = rsaUtil.getKeyMap().get("publicKey");// privateKey_s =rsaUtil.getKeyMap().get("privateKey");System.out.println("<--- 1 --->服务器端生成公钥:" +publicKey_s );// System.out.println("<--- 1 --->服务器端生成私钥:"+ privateKey_s);System.out.println("<--- 1 --->服务器端生成私钥,不公开");System.out.println("<--- 2 --->客户端获取到服务器端给定的公钥:"+ publicKey_s);System.out.println("<--- 3 --->客户端用此公钥执行加密,加密原始数据:xhy 我爱你 中国 依芸Yiyun !!!");// 客户端用服务器端的公钥生成的密文String cipherText_c ="eCOu/WkaQ8tZHk2u+Y9bh6RKOVMQGsssjnQB5DVlUeDPhjiIybeQSe7JH7fG5FgsucCi6uFwdU7yWzmkJFmMKGnE1pGLReqSaWgecviSTl1P4jjrq84VJvreoeCmcNUCoqxQvmYuMxB/D4rZ+PTuv0B2sQ4Q5fOH6fbqoj3uD5w=";cipherText_c ="MoYui9R3RZ+OYamuTvwAGWy2u8rllBQpjGzTXzje9aUM/KiD5nt8DYf1wna5a7DkBYpZ0CRVNHtOHiHgmrheBkpLuAXdh58eVn2hFLn0xCXqIRk+yEZSrF8fHJ7EBhE00WcyfqOoAM+uum57DFxtvATcEnFiEdkRb32JWkumdIY=";System.out.println("<--- 3 --->客户端生成的加密数据:"+cipherText_c);System.out.println("<--- 4 --->客户端生成自己的公钥:"+ publicKey_c);// System.out.println("<--- 4 --->客户端生成自己的私钥:"+ privateKey_c);System.out.println("<--- 4 --->客户端生成自己的私钥,不公开");// 客户端利用自己的私钥生成摘要后进行的签名String  signedText_c = "uFy+PqjxdxusV5+a9VR0cvk1XY0+Th8jWBT581irWVEDyzq00xGphQ8KIyApgvPw5+KP1DB/M7tMfd0viUT4w8i4VcyhGmRlk0XNkuRhQDgcWeZ5XKIoJ1ORQ0ecxcAAAAlPwMe2wCbPClXFmhJzypJtS7nKFzE/oeZg7nr91zg=";signedText_c ="reCyRzzxeo1i269BdV5TBrYqiYNyWEmk+i6Oxq/0MJz581tThBikh6/Z+hTZ3vY03UngoXwxB7pZBPW7FUxtwdqS8FcKtlVShaz0ZwU22BHbqFBvCvr4C224HQAdNeVoeHb3o8O/DEjNruUzM1NkweLqayI0unieRYxebvCweTE=";System.out.println("<--- 4 --->客户端利用自己的私钥生成摘要而后签名数据:"+signedText_c);System.out.println("<--- 5 --->客户端发送数据至服务器端,1自己的公钥,2自己的加密数据,3自己的签名数据");System.out.println("<--- 6 --->服务器端接收到来自客户端的数据:1客户端的公钥,2客户端的加密数据,3客户端的签名数据");System.out.println("<--- 6 --->1客户端的公钥:"+publicKey_c);System.out.println("<--- 6 --->2客户端的加密数据:"+cipherText_c);System.out.println("<--- 6 --->3客户端的签名数据:"+signedText_c);boolean isPassed = rsaUtil.verifySignPublicKey(cipherText_c, signedText_c, publicKey_c, true,true,false);System.out.println("<--- 7 --->服务器端用自己的公钥进行签名验证,结果:"+isPassed);if (isPassed){System.out.println("<--- 8 --->服务器端验签成功,开始解密数据...");String  plainText = "";plainText = rsaUtil.decryptByPrivateKey(cipherText_c,privateKey_s,true,true,false);System.out.println("<--- 9 --->服务器端用自己的私钥解密数据成功:"+ plainText);}/* 测试代码// 服务器端用服务器端的公钥生成的密文String cipherText_s ="";String plainText = "xhy 我爱你 中国 依芸Yiyun !!!";cipherText_s = rsaUtil.encryptByPublicKey(plainText, publicKey_s,true, true,false);System.out.println("服务器端执行加密,公钥加密:"+cipherText_s);// 服务器端利用客户端的私钥进行签名String  signedText_s = rsaUtil.signByPrivateKey(cipherText_c, privateKey_c,true, true,false);System.out.println("服务器端执行签名,私钥签名:"+signedText_s);*//* String  privateKey_c = "MIICXAIBAAKBgQDQPgskvyi9D/IuD0x73M2UOxBH3daAGbxLfUiSraG3cEgZCp7/o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHvvVgddaCvaFZkcIno4EVtHCLldKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9iFi2KDWwF30e2PHRpRQIDAQABAoGARuvaf7la9ojnwigTtFuO6Fz1PoSe+SHKrysL/GiGGyNyapTjccz+eAcaA5Ek8WO6K7S7nRZpeKzAGsS92aQmt66BpOqI+JJ2uM+K1HzH5K5rQ4rnaC/Hbd+4zsltVzuLbsICDGSlkpTSKK5YdIkA5YPMXoQek4zoYpUnKT2AxEECQQDoDrjIJ4MllIpc" +"gAWjahga1YrcTIcQPBwG9rfX7zk2nKFZF5rOB6iDHjE9mo9EOD/s7j3Z5eefwVkp" +"hRnbXJp3AkEA5bpMSf8zyBKfMZll3vdtDTDqnsVzOu89RxQYgceyWZ/OcFgvc9hg" +"NYoV/EkGQXcHWL1gPQwWpMRfS8L/DjbNIwJBAL3NBL/Y6YB8TOq5X2M4bHzOOiRT" +"h4j00Su08ctxA8eyNpnrH5fyVZbgw/+SAioXI9oDRp2JWHinKOk3z11HEaMCQDI/" +"qLY60xm9MQMJWaYGmtzayUcHS2glslKcy6t/gbxm3yHluCNvvcOYO6zeUDb7kSjQ" +"638O6NkLdwi8U0vJot8CQHEfumEFZ0LYbz914TZOWe2q0UKOUZaHgQIwoJ3n2yxJ" +"p7Ps3k9t2Of8Tm+HqZYCkSz8henOM8aFCS2GPD8Pkf4=" ;*/}

客户端vue:

工具类,常用加解密算法,enDecrypt.js

 /* base64 加解密*/export let Base64 = require('js-base64').Base64/* md5 加解密*/export let crypto = require('crypto');export let md5 = require('js-md5');export let CryptoJS = require('crypto-js');export let MD5 = CryptoJS.MD5;/**引入jsencrypt实现数据RSA加密*/import JSEncrypt from 'jsencrypt';// jsencrypt.js处理长文本数据时报错  Message too long for RSA// encryptlong是基于jsencrypt扩展的长文本分段加解密功能。import Encrypt from "encryptlong";// rsa signimport jsrsasign from 'jsrsasign'// Message Digest algorithm 5,信息摘要算法// alglorithm:md5、sha1、sha256export function Md5(plainText, alglorithm, encoding){const hash =  crypto.createHash(alglorithm)hash.update(plainText);//加密内容return  hash.digest(encoding);//密文}//Hash Message Authentication Code,散列消息鉴别码//Secure Hash Algorithm,安全散列算法//alglorithm:md5、sha256、sha1export function HMac(plainText, secretKey,alglorithm, encoding){const hmac= crypto.createHmac(alglorithm, secretKey);const cipherText= hmac.update(plainText);//加密内容return  cipherText.digest(encoding);//密文}// Data Encryption Standard,数据加密算法// DES/DES3/AES 加密, key与iv长度必须是8的倍数// mode:CryptoJS.mode.CBC、CryptoJS.mode.ECB、CryptoJS.mode.CFB// padding:CryptoJS.pad.ZeroPadding、CryptoJS.pad.Pkcs7、CryptoJS.pad.NoPaddingexport function encrypt ( algorithm, plainText,key, iv, mode, padding, isTextBase64) {key = key ? key : "abcdefghijklmnop";iv = iv ? iv : "0102030405060708";const keyHex = CryptoJS.enc.Utf8.parse(key);const ivHex = CryptoJS.enc.Utf8.parse(iv);const option = { iv:keyHex,mode: mode, padding: padding }let encrypted = null  ;if(algorithm === "TripleDES"){encrypted = CryptoJS.TripleDES.encrypt(plainText, keyHex, option)}else if(algorithm === "DES"){encrypted = CryptoJS.DES.encrypt(plainText, keyHex, option)}else if(algorithm === "AES"){encrypted =  CryptoJS.AES.encrypt(plainText, keyHex, option)}return isTextBase64?CryptoJS.enc.Base64.stringify(encrypted.ciphertext):encrypted.ciphertext.toString();}// DES/DES3/AES解密,key与iv长度必须是8的倍数export function decrypt (algorithm,cipherText,key, iv, mode, padding, isTextBase64) {key = key ? key : "abcdefghijklmnop";iv = iv ? iv : "0102030405060708";const keyHex = CryptoJS.enc.Utf8.parse(key);const ivHex = CryptoJS.enc.Utf8.parse(iv);const decryptText = isTextBase64?  CryptoJS.enc.Base64.parse(cipherText):cipherText;const textHex = { ciphertext:  isTextBase64?decryptText:CryptoJS.enc.Hex.parse(decryptText) }const option = { iv:ivHex,mode: mode, padding: padding }let decrypted = null;if(algorithm === "TripleDES"){decrypted = CryptoJS.TripleDES.decrypt(textHex, keyHex, option);}else if(algorithm === "DES"){decrypted = CryptoJS.DES.decrypt(textHex, keyHex, option);}else if(algorithm === "AES"){decrypted =  CryptoJS.AES.decrypt(textHex, keyHex, option);}return decrypted.toString(CryptoJS.enc.Utf8);}export function stringToHex(strSource) {if(strSource === "")return "";var hexCharCode = [];for(var i = 0; i < strSource.length; i++) {hexCharCode.push((strSource.charCodeAt(i)).toString(16));}return hexCharCode.join("");}export function hexToString(hexCharCodeStr) {var trimedStr = hexCharCodeStr.trim();var len = trimedStr.length;if(len % 2 !== 0) {alert("Illegal Format ASCII Code!");return "";}var curCharCode;var resultStr = [];for(var i = 0; i < len;i = i + 2) {curCharCode = parseInt(trimedStr.substr(i, 2), 16); // ASCII Code ValueresultStr.push(String.fromCharCode(curCharCode));}return resultStr.join("");}/** RSA 加密过程* (1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保留。公钥为公开的,任何人可以获取。* (2)A传递自己的公钥给B,B用A的公钥对消息进行加密。* (3)A接收到B加密的消息,利用A自己的私钥对消息进行解密。*  在这个过程中,只有2次传递过程,第一次是A传递公钥给B,第二次是B传递加密消息给A,即使都被敌方截获,也没有危险性。*  因为只有A的私钥才能对消息进行解密,防止了消息内容的泄露。*  使用方法*  客户端初始化访问服务器端时,服务器端会生成一对RSA对,及公钥和密钥。*  如果前端只需要将要传给后端的数据进行加密后传输,那么前端可以只要公钥,通过公钥对要传输的参数进行加密后把加密的字符串发给后端,后端取出保存的密码种子或者直接保存的私钥,采用私钥对加密字符串进行解密,得到明文。*  如果前端要获取后端传过来的已经加密后的字符串,并且解密使用,那么前端就需要拿到RSA对立面的私钥进行解密后使用了。* *//* JSEncrypt 公钥加密  padding:pkcs1pad2 */export function RsaJSEncrypt(plainText,publicKey,isKeyBase64,isTextBase64,isURLCode) {const jsencrypt = new JSEncrypt({default_key_size: 1024});// setPublicKey 参数默认需要base64,如果是十六进制编码则需要转换为base64,jsrsasign.b64tohex,jsrsasign.hextob64isKeyBase64?jsencrypt.setPublicKey(publicKey):jsencrypt.setPublicKey( jsrsasign.hextob64(publicKey));// 如果是对象/数组的话,需要先JSON.stringify转换成字符串// 处理中文乱码,服务器端:String result = java.net.URLDecoder.decode(cipherText ,"UTF-8");let  cipherText = jsencrypt.encrypt(plainText);// 默认加密结果为base64编码cipherText = isTextBase64?cipherText:jsrsasign.b64tohex(cipherText);// +号服务器端不识别,url编码cipherText = isURLCode? encodeURIComponent(cipherText):cipherText;return  cipherText;}/* JSEncrypt 私钥解密 padding:pkcs1pad2 */export function RsaJSDecrypt(cipherText,privateKey,isKeyBase64,isTextBase64,isURLCode) {const jsencrypt = new JSEncrypt({default_key_size: 1024,padding: crypto.constants.RSA_PKCS1_PADDING});isKeyBase64?jsencrypt.setPrivateKey(privateKey):jsencrypt.setPrivateKey(jsrsasign.hextob64(privateKey));cipherText = isURLCode?decodeURIComponent(cipherText):cipherText;cipherText = isTextBase64?cipherText:jsrsasign.b64tohex(cipherText);return jsencrypt.decrypt(cipherText);}/* 长文本分段加密 */export function RsaEncrypt(plainText,publicKey,isKeyBase64,isTextBase64,isURLCode) {const encryptor = new Encrypt({default_key_size: 1024,padding: crypto.constants.RSA_PKCS1_PADDING});if (isKeyBase64) {encryptor.setPublicKey(publicKey)}else {encryptor.setPublicKey(jsrsasign.hextob64(publicKey));}// 处理中文乱码,服务器端:String result = java.net.URLDecoder.decode(cipherText ,"UTF-8");let cipherText = encryptor.encryptLong(plainText);cipherText = isTextBase64?cipherText:jsrsasign.hextob64(cipherText);// +号服务器端不识别,url编码cipherText = isURLCode? encodeURIComponent(cipherText):cipherText;return  cipherText;}/* 长文本分段解密 */export function RsaDecrypt(cipherText,privateKey,isKeyBase64,isTextBase64,isURLCode) {const encryptor = new Encrypt({default_key_size: 1024,padding: crypto.constants.RSA_PKCS1_PADDING})if (isKeyBase64){encryptor.setPrivateKey(privateKey)}else{encryptor.setPrivateKey(jsrsasign.hextob64(privateKey));}cipherText = isURLCode?decodeURIComponent(cipherText):cipherText;cipherText = isTextBase64?cipherText:jsrsasign.b64tohex(cipherText);return encryptor.decryptLong(cipherText);}// 获取签名 privateKeyexport function RsaSign(plainText,privateKey,format_key, algorithm,isKeyBase64,isTextBase64,isURLCode){// 生成签名对象let sign = genSign(isKeyBase64?privateKey:jsrsasign.hextob64(privateKey),format_key, algorithm);plainText = isTextBase64?jsrsasign.b64tohex(plainText):plainText;// console.log("待签名前数据:"+plainText);let plain_Text = genDigest(plainText,algorithm);// console.log("待签名摘要数据:"+plain_Text);sign.updateString(plain_Text);// 默认签名数据为十六进制数据let signedText = isTextBase64?jsrsasign.hextob64(sign.sign()):sign.sign();// console.log("生成签名数据:"+sign.sign());// +号服务器端不识别,url编码signedText = isURLCode? encodeURIComponent(signedText):signedText;return signedText;}// 验证签名 publicKey_s 服务器端的公钥// alglorithm: SHA1withRSA、MD5withRSA、SHA256withRSA、 SHA384withRSA、SHA512withRSA、RIPEMD160withRSA// format_key: PKCS#1、PKCS#5、PKCS#8/** PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封。* PKCS#3:定义Diffie-Hellman密钥交换协议。* PKCS#5:描述一种利用从口令派生出来的安全密钥加密字符串的方法。使用MD2或MD5 从口令中派生密钥,并采用DES-CBC模式加密。主要用于加密从一个计算机传送到另一个计算机的私人密钥,不能用于加密消息[24]。* PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式。* PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息[26]。* PKCS#8:描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等。* PKCS#9:定义一些用于PKCS#6证书扩展、PKCS#7数字签名和PKCS#8私钥加密信息的属性类型。* PKCS#10:描述证书请求语法。* PKCS#11:称为Cyptoki,定义了一套独立于技术的程序设计接口,用于智能卡和PCMCIA卡之类的加密设备。* PKCS#12:描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法。* PKCS#13:椭圆曲线密码体制标准。* PKCS#14:伪随机数生成标准。* PKCS#15:密码令牌信息格式标准。*/export function RsaVerifySign(plainText,signedText,publicKey,format_key, algorithm,isKeyBase64,isTextBase64,isURLCode){// 生成签名let verifySign = genSign(isKeyBase64?publicKey:jsrsasign.hextob64(publicKey),format_key, algorithm);plainText = isTextBase64?jsrsasign.b64tohex(plainText):plainText;// 根据明文生成摘要let digestText = genDigest(plainText,algorithm);verifySign.updateString(digestText);signedText = isURLCode?decodeURIComponent(signedText):signedText;signedText = isTextBase64?jsrsasign.b64tohex(signedText):signedText;return  verifySign.verify(signedText);}// 根据明文生成摘要//SHA1withRSA、MD5withRSA、SHA256withRSA、 SHA384withRSA、SHA512withRSA、RIPEMD160withRSAexport function genDigest(plainText,algorithm ){let option = { "alg": algorithm.split('w')[0], "prov":"cryptojs/jsrsa", }// console.log("算法:"+algorithm.split('w')[0]);let text = new jsrsasign.KJUR.crypto.MessageDigest(option);   // 摘要text.updateString(plainText);let digestText = text.digest();// console.log("摘要:"+digestText);return digestText;}/* 生成rsa签名对象* */export function genSign(RsaKey,format_key, algorithm){// 密钥要写开头和结束// var private_key = '-----BEGIN PRIVATE KEY-----' + privateKey_s + '-----END PRIVATE KEY-----'// 读取解析pem格式的秘钥, 生成秘钥实例 (RSAKey)let rsaKey = new jsrsasign.RSAKey();if (format_key === "PKCS#1" || format_key === "PKCS#5"|| format_key === "PKCS#7"|| format_key === "PKCS#8") {rsaKey = jsrsasign.KEYUTIL.getKey(RsaKey);// rsaSign.readPrivateKeyFromPEMString(privateKey_s);}let option= {"alg":algorithm,"prov":"cryptojs/jsrsa","prvkeypem": rsaKey};let sign = new jsrsasign.KJUR.crypto.Signature(option);sign.init(rsaKey);return sign;}

前端使用代码流程:

 // 测试前后端使用流程// 1、后端生成密钥对,公钥分享给前端,前端获取到服务器给的公钥。// 2、前端用服务器端给的公钥 及算法:RSA/CBC/PKCS1Padding 加密"xhy 我爱你 中国 依芸Yiyun !!!" 生成加密数据。// 3、前端然后生成自己的密钥对,用自己的私钥及算法SHA1withRSA生成摘要签名。// 4、前端把加密数据、自己的公钥与签名一并发给后端。// 3、后端收到加密数据、签名数据、前端的公钥,先用前端公钥、签名数据、算法SHA1withRSA 验签,验签通过后再用后端的私钥、算法:RSA/CBC/PKCS7Padding 解密数据。// 注意:密钥与密文全部base64编码let  plainText = "xhy 我爱你 中国 依芸Yiyun !!!";let privateKey_c = "-----BEGIN RSA PRIVATE KEY-----" +"MIICXAIBAAKBgQDQPgskvyi9D/IuD0x73M2UOxBH3daAGbxLfUiSraG3cEgZCp7/" +"o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHvvVgddaCvaFZkcIno4EVtHCLl" +"dKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9iFi2KDWwF30e2PHRpRQIDAQAB" +"AoGARuvaf7la9ojnwigTtFuO6Fz1PoSe+SHKrysL/GiGGyNyapTjccz+eAcaA5Ek" +"8WO6K7S7nRZpeKzAGsS92aQmt66BpOqI+JJ2uM+K1HzH5K5rQ4rnaC/Hbd+4zslt" +"VzuLbsICDGSlkpTSKK5YdIkA5YPMXoQek4zoYpUnKT2AxEECQQDoDrjIJ4MllIpc" +"gAWjahga1YrcTIcQPBwG9rfX7zk2nKFZF5rOB6iDHjE9mo9EOD/s7j3Z5eefwVkp" +"hRnbXJp3AkEA5bpMSf8zyBKfMZll3vdtDTDqnsVzOu89RxQYgceyWZ/OcFgvc9hg" +"NYoV/EkGQXcHWL1gPQwWpMRfS8L/DjbNIwJBAL3NBL/Y6YB8TOq5X2M4bHzOOiRT" +"h4j00Su08ctxA8eyNpnrH5fyVZbgw/+SAioXI9oDRp2JWHinKOk3z11HEaMCQDI/" +"qLY60xm9MQMJWaYGmtzayUcHS2glslKcy6t/gbxm3yHluCNvvcOYO6zeUDb7kSjQ" +"638O6NkLdwi8U0vJot8CQHEfumEFZ0LYbz914TZOWe2q0UKOUZaHgQIwoJ3n2yxJ" +"p7Ps3k9t2Of8Tm+HqZYCkSz8henOM8aFCS2GPD8Pkf4=" +"-----END RSA PRIVATE KEY-----";let publicKey_c ="-----BEGIN PUBLIC KEY-----" +"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQPgskvyi9D/IuD0x73M2UOxBH" +"3daAGbxLfUiSraG3cEgZCp7/o1RKM/Uckoplw/DDD665je4wVc0R2zZ8E9LQrrHv" +"vVgddaCvaFZkcIno4EVtHCLldKOFzAIr8ucxCHelV9oGhrcCmeGwYnVTeXOerY9i" +"Fi2KDWwF30e2PHRpRQIDAQAB" +"-----END PUBLIC KEY-----";let publicKey_s = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHykT0c0tGvUYNS0Is5HyC9XIgDBBbOObZePREbsCANZHFK7QdQo492yjCztEqe/fdhAjllWbBOg2T5Xt5FWBbnyAU+KY0daCakbOGfYOW5MGOqe+N3hp09aca4uSzagXXr5SrI6sHHyHToSKs9gWnjNz09TudjyPXvlONFxK4uwIDAQAB";console.log("<--- 2 --->客户端获取到服务器端给定的公钥:"+ publicKey_s);let cipherText_c =this.$RsaEncrypt(plainText,publicKey_s,true,true,false);console.log("<--- 3 --->客户端利用服务器端的公钥加密数据,生成密文,base64编码输出\n"+cipherText_c);// 记录 cipherText_c = "eCOu/WkaQ8tZHk2u+Y9bh6RKOVMQGsssjnQB5DVlUeDPhjiIybeQSe7JH7fG5FgsucCi6uFwdU7yWzmkJFmMKGnE1pGLReqSaWgecviSTl1P4jjrq84VJvreoeCmcNUCoqxQvmYuMxB/D4rZ+PTuv0B2sQ4Q5fOH6fbqoj3uD5w=";let signedText_c = this.$RsaSign(cipherText_c,privateKey_c,"PKCS#8","SHA1withRSA",true,true,false);console.log("<--- 4 --->客户端生成自己的公钥\n"+publicKey_c);console.log("<--- 4 --->客户端利用自己生成的私钥签名数据,生成摘要与签名\n"+signedText_c);console.log("<--- 5 --->客户端发送数据至服务器端,1客户端的公钥,2客户端的加密数据,3客户端的签名数据\n");// 记录 signedText_c = "uFy+PqjxdxusV5+a9VR0cvk1XY0+Th8jWBT581irWVEDyzq00xGphQ8KIyApgvPw5+KP1DB/M7tMfd0viUT4w8i4VcyhGmRlk0XNkuRhQDgcWeZ5XKIoJ1ORQ0ecxcAAAAlPwMe2wCbPClXFmhJzypJtS7nKFzE/oeZg7nr91zg=";// 注意:加密密文与签名都是唯一的,不会变化。// 注意:vue 端密钥都要带头。// 注意:vue端及java端函数参数要求是什么类型及何进制。搞明白哪里用base64,哪里2进制,哪里16进制。// 重点还是要了解点原理,比如sha1withrsa,先经过sha1算法,知道aaa,哈希后的密文16进制是:7e240de74fb1ed08fa08d38063f6a6a91462a815,对比自己的程序有没有算错。// 利用一些在线测试工具帮忙验证自己的程序过程。http://www.metools.info/code/c82.html ; 同时知道如何查引入的类库各api的官网,了解如何使用各函数。// 不然遇到莫名奇妙的错误无从解决。报错的地方不一定是程序实际错误的地方。了解查错的方式有:打庄、debug./* 仅供测试使用,加密数据及验签let privateKey_s = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIfKRPRzS0a9Rg1LQizkfIL1ciAMEFs45tl49ERuwIA1kcUrtB1Cjj3bKMLO0Sp7992ECOWVZsE6DZPle3kVYFufIBT4pjR1oJqRs4Z9g5bkwY6p743eGnT1pxri5LNqBdevlKsjqwcfIdOhIqz2BaeM3PT1O52PI9e+U40XEri7AgMBAAECgYAmNYNLqbmP0SiKCxg226AxlXEklWBw2sUSgpdxPhzKtsgqzA5lgVnXC/kfP+TZaIKpgUKjn3OHgZdae2NQAfTXxTcvhNGYSOeJ8VgslQueoJW7ypgQ/IoNy2DeglObAJ3uCgA4F566j6H7IvcllKGmDT/6PUlljxZJpBMfslspgQJBAP19EMRxmV4vYL7o55oR397UEUXn3vO88SPo2gxaPZ/ltzgaHM5R1zALPE1EfPIPqVdGf2hcowr22pC1BG+nlXsCQQCJIq4USfgNmjGwquo5PyksQ9vsYc/OxGBxEqTpVez24eJb7tvoqvbYfpleeEyWgtvzHqnlY24QdONhVVm5zOXBAkAxt7PwM6+3D2fUSe4TA+p60/FHWsEZ4TcSqfsKbTClCfMzp7t6pAamv61mIka3W2cFXShkGbdI0T3xH+/szlu9AkBi3SSgrd7td39hPSaU1MsLBXT0SmO1Te+1NNq8+VxXc+trmZzidPZ2h3ZsG9AjJf4JnM6g9/iuVoZiclS4VVZBAkEAsPkIGRvX4Nj3ljiBjgdJ68JRZC3gK/kXLNeefIeHg6F/4eyg729PlfdD2mvPb8hiszvsT1zvF8gvxGi4lT6B/w==" ;console.log("RSAVerifySign_pubK="+this.$RsaVerifySign(cipherText_c, signedText_c,publicKey_c,"PKCS#8","SHA1withRSA",true,true,false));plainText = "";plainText = this.$RsaDecrypt(cipherText_c, privateKey_s,true,true,false)console.log("RSADe_priK="+plainText);*/

测试结果截图说明

服务器:

客户端:

前后端java+vue 实现rsa 加解密与摘要签名算法相关推荐

  1. Java中的RSA加解密工具类:RSAUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt;import com.mirana.frame.utils.log.LogUtils; ...

  2. 与非java语言使用RSA加解密遇到的问题:algid parse error, not a sequence

    遇到的问题 在一个与Ruby语言对接的项目中,决定使用RSA算法来作为数据传输的加密与签名算法.但是,在使用Ruby生成后给我的私钥时,却发生了异常:IOException: algid parse ...

  3. java rsa_java中RSA加解密的实现

    public static void main(String[] args) throws Exception { // TODO Auto-generated method stub HashMap ...

  4. openssl在多平台和多语言之间进行RSA加解密注意事项

    首先说一下平台和语言: 系统平台为CentOS6.3,RSA加解密时使用NOPADDING进行填充 1)使用C/C++调用系统自带的openssl 2)Android4.2模拟器,第三方openssl ...

  5. VUE内使用RSA加解密

    说明:为防止私钥泄漏,由服务端生成两对密钥,分别是(前端公钥+私钥,后端公钥加私钥),采用加解密模式为:前端使用后台公钥加密,使用前端私钥解密:后端使用前端公钥加密,使用后端私钥解密.前后端统一使用公 ...

  6. Java实现图片上传功能(前后端:vue+springBoot)

    Java实现图片上传功能(前后端:vue+springBoot) 前言: 前端: 组件引入 基础文件上传 自定义上传方法 后端: 需要引入的jar包: 基础文件上传 Controller层: serv ...

  7. RSA加解密用途简介及java示例

    在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证.对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每 ...

  8. openresty 与 java RSA加解密

    上一篇搞定了openresty与java之间的aes加解密.这一篇就来说说openresty与java之间RSA的加解密.在测试的过程中.发现了与aes同样的问题.就是openresty支持的填充模式 ...

  9. RSA加解密,.net公钥/私钥兼容java

    背景介绍 之前老程序使用.net进行数据的RSA加解密,现在用JAVA重写,但是.net的公钥和私钥是xml格式,跟java的不一样,需要手动转换一下.目前网上的大部分都是java转.net.我这里来 ...

最新文章

  1. 图像补运算:MatIterator_迭代器反色处理
  2. CTFshow 命令执行 web35
  3. 西南民族大学计算机考试试题,西南民族大学预科教育学院 2007级《计算机》模拟试题(含答案)...
  4. split函数python 未定义_实现python 的split函数
  5. [Bzoj2049][Sdoi2008]Cave 洞穴勘测
  6. css3弹性盒子+小程序布局
  7. linux常用快捷键大全
  8. linux文件编程 --- fflush函数
  9. 支付业务与技术架构学习总结(7)——从金融牌照(三方支付牌照),看互联网巨头的金融布局
  10. 怎么用cmd强制修改密码
  11. Openfire使用总结
  12. 【数据结构】线段树的扩展与应用
  13. python实现键盘记录木马
  14. 移动Web MUI框架Switch开关自定义中文文字
  15. 03——axios配置对象以及默认配置
  16. APP攻防——微信小程序解包反编译数据抓包APK资源提取
  17. 高数——积分上限函数
  18. 3、计算机如何执行指令
  19. 身份证输入框测试点分析
  20. 全面的Swift学习资料整理

热门文章

  1. 什么是token?有什么用?
  2. CTR预估模型的进化之路
  3. 详细讲解C语言单机小游戏——打字母游戏
  4. 【82期分享】4款中国风PPT模板免费下载
  5. Linux操作系统下连接闪讯的方法(支持有线与无线)
  6. Java--IO流详解
  7. vue打包nginx部署
  8. 抖音、拼多多、趣头条告诉我们:一切商业均有机会
  9. Latex之修改参考文献reference的字体大小
  10. 计算机在工程设计的应用,计算机辅助软件和网络技术在工程设计中的应用