前后端java+vue 实现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 加解密与摘要签名算法相关推荐
- Java中的RSA加解密工具类:RSAUtils
本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt;import com.mirana.frame.utils.log.LogUtils; ...
- 与非java语言使用RSA加解密遇到的问题:algid parse error, not a sequence
遇到的问题 在一个与Ruby语言对接的项目中,决定使用RSA算法来作为数据传输的加密与签名算法.但是,在使用Ruby生成后给我的私钥时,却发生了异常:IOException: algid parse ...
- java rsa_java中RSA加解密的实现
public static void main(String[] args) throws Exception { // TODO Auto-generated method stub HashMap ...
- openssl在多平台和多语言之间进行RSA加解密注意事项
首先说一下平台和语言: 系统平台为CentOS6.3,RSA加解密时使用NOPADDING进行填充 1)使用C/C++调用系统自带的openssl 2)Android4.2模拟器,第三方openssl ...
- VUE内使用RSA加解密
说明:为防止私钥泄漏,由服务端生成两对密钥,分别是(前端公钥+私钥,后端公钥加私钥),采用加解密模式为:前端使用后台公钥加密,使用前端私钥解密:后端使用前端公钥加密,使用后端私钥解密.前后端统一使用公 ...
- Java实现图片上传功能(前后端:vue+springBoot)
Java实现图片上传功能(前后端:vue+springBoot) 前言: 前端: 组件引入 基础文件上传 自定义上传方法 后端: 需要引入的jar包: 基础文件上传 Controller层: serv ...
- RSA加解密用途简介及java示例
在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证.对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每 ...
- openresty 与 java RSA加解密
上一篇搞定了openresty与java之间的aes加解密.这一篇就来说说openresty与java之间RSA的加解密.在测试的过程中.发现了与aes同样的问题.就是openresty支持的填充模式 ...
- RSA加解密,.net公钥/私钥兼容java
背景介绍 之前老程序使用.net进行数据的RSA加解密,现在用JAVA重写,但是.net的公钥和私钥是xml格式,跟java的不一样,需要手动转换一下.目前网上的大部分都是java转.net.我这里来 ...
最新文章
- 图像补运算:MatIterator_迭代器反色处理
- CTFshow 命令执行 web35
- 西南民族大学计算机考试试题,西南民族大学预科教育学院 2007级《计算机》模拟试题(含答案)...
- split函数python 未定义_实现python 的split函数
- [Bzoj2049][Sdoi2008]Cave 洞穴勘测
- css3弹性盒子+小程序布局
- linux常用快捷键大全
- linux文件编程 --- fflush函数
- 支付业务与技术架构学习总结(7)——从金融牌照(三方支付牌照),看互联网巨头的金融布局
- 怎么用cmd强制修改密码
- Openfire使用总结
- 【数据结构】线段树的扩展与应用
- python实现键盘记录木马
- 移动Web MUI框架Switch开关自定义中文文字
- 03——axios配置对象以及默认配置
- APP攻防——微信小程序解包反编译数据抓包APK资源提取
- 高数——积分上限函数
- 3、计算机如何执行指令
- 身份证输入框测试点分析
- 全面的Swift学习资料整理