当前位置: 首页 > news >正文

rsa加签验签C#和js、java、微信小程序互通

js实现rsa加签验签

https://github.com/kjur/jsrsasign
11.1.0版本
解压选择需要的版本,这里选择all版本了
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>JS RSA加签验签</title>
</head>
<body></body>
<script src="jsrsasign-all-min.js"></script>
<script type="text/javascript">// 公钥let pk = "-----BEGIN PUBLIC KEY-----\n" +"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3XSdz1MnzazBEN5KOfTx0IyVJ\n" +"Z5wb57isrCuHDhnYXwtmdhQalgII0fozeeFpMpAvlnmHC1kpW7XVGvZnLx3bWbCE\n" +"bf+pMSW4kmQuI+5cxRUJbCl7sdaODBrINgERHPICVC18AJLThEVMHyjuR6Jn4zQm\n" +"yYNbReSktY/BrFTvMQIDAQAB\n" +"-----END PUBLIC KEY-----";// 私钥let priK = "-----BEGIN PRIVATE KEY-----\n" +"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPddJ3PUyfNrMEQ3\n" +"ko59PHQjJUlnnBvnuKysK4cOGdhfC2Z2FBqWAgjR+jN54WkykC+WeYcLWSlbtdUa\n" +"9mcvHdtZsIRt/6kxJbiSZC4j7lzFFQlsKXux1o4MGsg2AREc8gJULXwAktOERUwf\n" +"KO5HomfjNCbJg1tF5KS1j8GsVO8xAgMBAAECgYEA6eG1JMrj63jEmStmMb1txG1a\n" +"mu4Q5z2QGgtr2HVXsIIlGEq6tWxyHf7TL4qkuz9onuYKn8n2Eqm44fZtVaBx+5ES\n" +"zRpIvlTvaxmVu0HZ1hYAzUw1XyRnXNMKpL5tT4GCjm8+QGPzlGxgXI1sNg8r9Jaw\n" +"9zRUYeA6LQR9RIMkHWUCQQD8QojjVoGjtiunoh/N8iplhUszZIavAEvmDIE+kVy+\n" +"pA7hvlukLw6JMc7cfTcnHyxDo9iHVIzrWlTuKRq9KWVLAkEA+wgJS2sgtldnCVn6\n" +"tJKFVwsHrWhMIU29msPPbNuWUD23BcKE/vehIyFu1ahNA/TiM40PEnzprQ5JfPxU\n" +"16S78wJANTfMLTnYy7Lo7sqTLx2BuD0wqjzw9QZ4/KVytsJv8IAn65P/PVn4FRV+\n" +"8KEx+3zmF7b/PT2nJRe/hycAzxtmlQJBAMrFwQxEqpXfoAEzx4lY2ZBn/nmaR/SW\n" +"4VNEXCbocVC7qT1j1R5HVMgV13uKiTtq8dUGWmhqsi7x3XayNK5ECPUCQQDZaAN6\n" +"tvIHApz9OLsXSw0jZirQ6KEYdharXbIVDy1W1sVE3lzLbqLdFp1bxAHQIvsYS5PM\n" +"A9veSJh372RLJKkj\n" +"-----END PRIVATE KEY-----";// 原文var src = "好厉害";src="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiMTU2MjEzNTc1MDEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ4MDY5NjUyNDQ4NDY3NyIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0";// 创建 Signature 对象let signature = new KJUR.crypto.Signature({alg: "SHA1withRSA", prvkeypem: priK});    //!这里指定 私钥 pem!signature.updateString(src);let a = signature.sign();let sign = hextob64(a);console.log("jsrsasign: \n"+sign);// 验签// !要重新new 一个Signature, 否则, 取摘要和签名时取得摘要不一样, 导致验签误报失败(原因不明)!let signatureVf = new KJUR.crypto.Signature({alg: "SHA1withRSA", prvkeypem: pk});signatureVf.updateString(src);// !接受的参数是16进制字符串!let b = signatureVf.verify(b64tohex(sign));console.log("jsrsasign verify: " + b);
</script>
</html>

在这里插入图片描述
也可以换成SHA256withRSA

vue中使用

npm i jsrsasign

使用

import jsrsasign from 'jsrsasign';
let signData="";//原始数据
let sign="";//base64格式签名
let publicKey="";//公钥
let signatureVf = new jsrsasign.Signature({alg: "SHA256withRSA", prvkeypem: publicKey});
signatureVf.updateString(signData);
// !接受的参数是16进制字符串!
let b = signatureVf.verify(jsrsasign.b64tohex(sign));

微信小程序使用

找到npm/lib下jsrsasign.js,底部有export的js就是
在这里插入图片描述

import jsrsasign from './jsrsasign'
/*** 验签*/
function veritify(data,sign,publickKey){let signatureVf = new jsrsasign.Signature({alg: "SHA256withRSA", prvkeypem: publickKey});signatureVf.updateString(data);let b = signatureVf.verify(jsrsasign.b64tohex(sign));return b;
}

C# 实现rsa加签验签

新建.net core3.1项目
安装BouncyCastle.Cryptography 2.4.0

RSAHelper

using System;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;namespace RSACSharpJsStu01
{public class RSAHelper{/// <summary>/// 重写FromXmlString方法/// </summary>/// <param name="xmlString"></param>/// <returns></returns>public static RSACryptoServiceProvider FromXmlString(string xmlString){var rsa = new RSACryptoServiceProvider();RSAParameters parameters = new RSAParameters();XmlDocument xmlDoc = new XmlDocument();xmlDoc.LoadXml(xmlString);if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue")){foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes){switch (node.Name){case "Modulus":parameters.Modulus = Convert.FromBase64String(node.InnerText);break;case "Exponent":parameters.Exponent = Convert.FromBase64String(node.InnerText);break;case "P":parameters.P = Convert.FromBase64String(node.InnerText);break;case "Q":parameters.Q = Convert.FromBase64String(node.InnerText);break;case "DP":parameters.DP = Convert.FromBase64String(node.InnerText);break;case "DQ":parameters.DQ = Convert.FromBase64String(node.InnerText);break;case "InverseQ":parameters.InverseQ = Convert.FromBase64String(node.InnerText);break;case "D":parameters.D = Convert.FromBase64String(node.InnerText);break;}}}else{throw new Exception("Invalid XML RSA key.");}rsa.ImportParameters(parameters);return rsa;}/// <summary>/// RSA公钥,从Java格式转.net格式(不依赖第三方包)/// </summary>/// <param name="publikKey"></param>/// <returns></returns>public static string RSAPublicKeyJava2DotNet(string publicKey){RsaKeyParameters publicKeyParam =(RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent></RSAKeyValue>",Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>        /// RSA签名验证/// </summary> /// <param name="encryptSource">签名</param>/// <param name="c">验证的字符串</param>/// <param name="publicKey">公钥</param>/// <returns>是否相同,true验证成功,false验证失败。</returns>public static bool VerifySignature(string encryptSource, string compareString, string publicKey){try{//.net core2.2及其以下版本使用,重写FromXmlString(string)方法//using RSACryptoServiceProvider rsa = FromXmlString(RSAPublicKeyJava2DotNet(publicKey));var rsa = new RSACryptoServiceProvider();rsa.FromXmlString(RSAPublicKeyJava2DotNet(publicKey)); //.net core3.0直接使用,不需要重写byte[] signature = Convert.FromBase64String(encryptSource);//SHA1Managed sha1 = new SHA1Managed();SHA256Managed sha256 = new SHA256Managed();RSAPKCS1SignatureDeformatter df = new RSAPKCS1SignatureDeformatter(rsa);df.SetHashAlgorithm("SHA256");byte[] compareByte = sha256.ComputeHash(Encoding.UTF8.GetBytes(compareString));return df.VerifySignature(compareByte, signature);}catch (Exception){return false;}}/// <summary>/// RSA私钥,从Java格式转.net格式(不依赖第三方包)/// </summary>/// <param name="privateKey">私钥</param>/// <returns></returns>public static string RSAPrivateKeyJava2DotNet(string privateKey){RsaPrivateCrtKeyParameters privateKeyParam =(RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKey));return string.Format("<RSAKeyValue><Modulus>{0}</Modulus><Exponent>{1}</Exponent><P>{2}</P><Q>{3}</Q><DP>{4}</DP><DQ>{5}</DQ><InverseQ>{6}</InverseQ><D>{7}</D></RSAKeyValue>",Convert.ToBase64String(privateKeyParam.Modulus.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.PublicExponent.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.P.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Q.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DP.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.DQ.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.QInv.ToByteArrayUnsigned()),Convert.ToBase64String(privateKeyParam.Exponent.ToByteArrayUnsigned()));}/// <summary>/// 私钥签名/// </summary>/// <param name="contentForSign"></param>/// <param name="privateKey"></param>/// <returns></returns>public static string Sign(string contentForSign, string privateKey){var netKey = RSAPrivateKeyJava2DotNet(privateKey); //转换成适用于.net的私钥//var rsa = FromXmlString(netKey); //.net core2.2及其以下版本使用,重写FromXmlString(string)方法var rsa = new RSACryptoServiceProvider();rsa.FromXmlString(netKey); //.net core3.0直接使用,不需要重写var rsaClear = new RSACryptoServiceProvider();var paras = rsa.ExportParameters(true);rsaClear.ImportParameters(paras); //签名返回//var sha1 = new SHA1CryptoServiceProvider();using (var sha256 = new SHA256CryptoServiceProvider()){var signData = rsa.SignData(Encoding.UTF8.GetBytes(contentForSign), sha256);return Convert.ToBase64String(signData);}}}
}

接口如下

using System.Text;
using Microsoft.AspNetCore.Mvc;namespace RSACSharpJsStu01.Controllers
{[ApiController]public class IndexController : ControllerBase{// 公钥private string pk = //"-----BEGIN PUBLIC KEY-----\n" +"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3XSdz1MnzazBEN5KOfTx0IyVJ\n" +"Z5wb57isrCuHDhnYXwtmdhQalgII0fozeeFpMpAvlnmHC1kpW7XVGvZnLx3bWbCE\n" +"bf+pMSW4kmQuI+5cxRUJbCl7sdaODBrINgERHPICVC18AJLThEVMHyjuR6Jn4zQm\n" +"yYNbReSktY/BrFTvMQIDAQAB\n"//+"-----END PUBLIC KEY-----";// 私钥private string priK = //"-----BEGIN PRIVATE KEY-----\n" +"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPddJ3PUyfNrMEQ3\n" +"ko59PHQjJUlnnBvnuKysK4cOGdhfC2Z2FBqWAgjR+jN54WkykC+WeYcLWSlbtdUa\n" +"9mcvHdtZsIRt/6kxJbiSZC4j7lzFFQlsKXux1o4MGsg2AREc8gJULXwAktOERUwf\n" +"KO5HomfjNCbJg1tF5KS1j8GsVO8xAgMBAAECgYEA6eG1JMrj63jEmStmMb1txG1a\n" +"mu4Q5z2QGgtr2HVXsIIlGEq6tWxyHf7TL4qkuz9onuYKn8n2Eqm44fZtVaBx+5ES\n" +"zRpIvlTvaxmVu0HZ1hYAzUw1XyRnXNMKpL5tT4GCjm8+QGPzlGxgXI1sNg8r9Jaw\n" +"9zRUYeA6LQR9RIMkHWUCQQD8QojjVoGjtiunoh/N8iplhUszZIavAEvmDIE+kVy+\n" +"pA7hvlukLw6JMc7cfTcnHyxDo9iHVIzrWlTuKRq9KWVLAkEA+wgJS2sgtldnCVn6\n" +"tJKFVwsHrWhMIU29msPPbNuWUD23BcKE/vehIyFu1ahNA/TiM40PEnzprQ5JfPxU\n" +"16S78wJANTfMLTnYy7Lo7sqTLx2BuD0wqjzw9QZ4/KVytsJv8IAn65P/PVn4FRV+\n" +"8KEx+3zmF7b/PT2nJRe/hycAzxtmlQJBAMrFwQxEqpXfoAEzx4lY2ZBn/nmaR/SW\n" +"4VNEXCbocVC7qT1j1R5HVMgV13uKiTtq8dUGWmhqsi7x3XayNK5ECPUCQQDZaAN6\n" +"tvIHApz9OLsXSw0jZirQ6KEYdharXbIVDy1W1sVE3lzLbqLdFp1bxAHQIvsYS5PM\n" +"A9veSJh372RLJKkj\n"//+"-----END PRIVATE KEY-----";[HttpGet("/rsa")]public string Get(){var src = "好厉害";src ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiMTU2MjEzNTc1MDEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ4MDY5NjUyNDQ4NDY3NyIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0";var sign = RSAHelper.Sign(src, priK);StringBuilder result = new StringBuilder();result.Append("加签结果:");result.Append(sign);var isSuccess = RSAHelper.VerifySignature(sign,src, pk);result.Append("验签结果:");result.Append(isSuccess + "");return result.ToString();}}
}

在这里插入图片描述
转化为RsaPemHelper

 public class PemHelper{static private Regex _PEMCode = new Regex(@"--+.+?--+|\s+");static private byte[] _SeqOID = new byte[] { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };static private byte[] _Ver = new byte[] { 0x02, 0x01, 0x00 };/// <summary>/// 用PEM格式密钥对创建RSA,支持PKCS#1、PKCS#8格式的PEM/// </summary>public static RSACryptoServiceProvider FromPEM(string pem){var rsaParams = new CspParameters();rsaParams.Flags = CspProviderFlags.UseMachineKeyStore;var rsa = new RSACryptoServiceProvider(rsaParams);var param = new RSAParameters();var base64 = _PEMCode.Replace(pem, "");var data = RSAUnitHelper.Base64DecodeBytes(base64);if (data == null){throw new Exception("PEM内容无效");}var idx = 0;//读取长度Func<byte, int> readLen = (first) => {if (data[idx] == first){idx++;if (data[idx] == 0x81){idx++;return data[idx++];}else if (data[idx] == 0x82){idx++;return (((int)data[idx++]) << 8) + data[idx++];}else if (data[idx] < 0x80){return data[idx++];}}throw new Exception("PEM未能提取到数据");};//读取块数据Func<byte[]> readBlock = () => {var len = readLen(0x02);if (data[idx] == 0x00){idx++;len--;}var val = data.sub(idx, len);idx += len;return val;};//比较data从idx位置开始是否是byts内容Func<byte[], bool> eq = (byts) => {for (var i = 0; i < byts.Length; i++, idx++){if (idx >= data.Length){return false;}if (byts[i] != data[idx]){return false;}}return true;};if (pem.Contains("PUBLIC KEY")){/****使用公钥****///读取数据总长度readLen(0x30);if (!eq(_SeqOID)){throw new Exception("PEM未知格式");}//读取1长度readLen(0x03);idx++;//跳过0x00//读取2长度readLen(0x30);//Modulusparam.Modulus = readBlock();//Exponentparam.Exponent = readBlock();}else if (pem.Contains("PRIVATE KEY")){/****使用私钥****///读取数据总长度readLen(0x30);//读取版本号if (!eq(_Ver)){throw new Exception("PEM未知版本");}//检测PKCS8var idx2 = idx;if (eq(_SeqOID)){//读取1长度readLen(0x04);//读取2长度readLen(0x30);//读取版本号if (!eq(_Ver)){throw new Exception("PEM版本无效");}}else{idx = idx2;}//读取数据param.Modulus = readBlock();param.Exponent = readBlock();param.D = readBlock();param.P = readBlock();param.Q = readBlock();param.DP = readBlock();param.DQ = readBlock();param.InverseQ = readBlock();}else{throw new Exception("pem需要BEGIN END标头");}rsa.ImportParameters(param);return rsa;}/// <summary>/// 将RSA中的密钥对转换成PEM格式,usePKCS8=false时返回PKCS#1格式,否则返回PKCS#8格式,如果convertToPublic含私钥的RSA将只返回公钥,仅含公钥的RSA不受影响/// </summary>public static string ToPEM(RSACryptoServiceProvider rsa, bool convertToPublic, bool usePKCS8){var ms = new MemoryStream();//写入一个长度字节码Action<int> writeLenByte = (len) => {if (len < 0x80){ms.WriteByte((byte)len);}else if (len <= 0xff){ms.WriteByte(0x81);ms.WriteByte((byte)len);}else{ms.WriteByte(0x82);ms.WriteByte((byte)(len >> 8 & 0xff));ms.WriteByte((byte)(len & 0xff));}};//写入一块数据Action<byte[]> writeBlock = (byts) => {var addZero = (byts[0] >> 4) >= 0x8;ms.WriteByte(0x02);var len = byts.Length + (addZero ? 1 : 0);writeLenByte(len);if (addZero){ms.WriteByte(0x00);}ms.Write(byts, 0, byts.Length);};//根据后续内容长度写入长度数据Func<int, byte[], byte[]> writeLen = (index, byts) => {var len = byts.Length - index;ms.SetLength(0);ms.Write(byts, 0, index);writeLenByte(len);ms.Write(byts, index, len);return ms.ToArray();};if (rsa.PublicOnly || convertToPublic){/****生成公钥****/var param = rsa.ExportParameters(false);//写入总字节数,不含本段长度,额外需要24字节的头,后续计算好填入ms.WriteByte(0x30);var index1 = (int)ms.Length;//固定内容// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"ms.writeAll(_SeqOID);//从0x00开始的后续长度ms.WriteByte(0x03);var index2 = (int)ms.Length;ms.WriteByte(0x00);//后续内容长度ms.WriteByte(0x30);var index3 = (int)ms.Length;//写入ModuluswriteBlock(param.Modulus);//写入ExponentwriteBlock(param.Exponent);//计算空缺的长度var byts = ms.ToArray();byts = writeLen(index3, byts);byts = writeLen(index2, byts);byts = writeLen(index1, byts);return "-----BEGIN PUBLIC KEY-----\n" + RSAUnitHelper.TextBreak(RSAUnitHelper.Base64EncodeBytes(byts), 64) + "\n-----END PUBLIC KEY-----";}else{/****生成私钥****/var param = rsa.ExportParameters(true);//写入总字节数,后续写入ms.WriteByte(0x30);int index1 = (int)ms.Length;//写入版本号ms.writeAll(_Ver);//PKCS8 多一段数据int index2 = -1, index3 = -1;if (usePKCS8){//固定内容ms.writeAll(_SeqOID);//后续内容长度ms.WriteByte(0x04);index2 = (int)ms.Length;//后续内容长度ms.WriteByte(0x30);index3 = (int)ms.Length;//写入版本号ms.writeAll(_Ver);}//写入数据writeBlock(param.Modulus);writeBlock(param.Exponent);writeBlock(param.D);writeBlock(param.P);writeBlock(param.Q);writeBlock(param.DP);writeBlock(param.DQ);writeBlock(param.InverseQ);//计算空缺的长度var byts = ms.ToArray();if (index2 != -1){byts = writeLen(index3, byts);byts = writeLen(index2, byts);}byts = writeLen(index1, byts);var flag = " PRIVATE KEY";if (!usePKCS8){flag = " RSA" + flag;}return "-----BEGIN" + flag + "-----\n" + RSAUnitHelper.TextBreak(RSAUnitHelper.Base64EncodeBytes(byts), 64) + "\n-----END" + flag + "-----";}}}

如果有部分密钥加密解密报错可以使用PemHelper.FromPEM替代FromXmlString
可以看到js加签和C#加签结果一样,所以验签也是通过的

java代码实现

SHA256withRSAUtil.java

package com.wujialiang;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;public class SHA256withRSAUtil {private static final String RSA = "RSA";private static final String SHA256WITHRSA = "SHA256withRSA";/*** 生成RSA密钥* @return* @throws NoSuchAlgorithmException*/public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);keyPairGenerator.initialize(2048, new SecureRandom());return keyPairGenerator.genKeyPair();}/*** 获取私钥* @param base64* @return*/public static PrivateKey getPrivateKey(String base64) throws Exception {// 解码Base64字符串回字节数组byte[] encodedPrivateKey = Base64.getDecoder().decode(base64);// 使用PKCS8EncodedKeySpec和KeyFactory来加载私钥PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);KeyFactory kf = KeyFactory.getInstance(RSA);PrivateKey privateKey = kf.generatePrivate(keySpec);return privateKey;}/*** 获取私钥* @param base64* @return*/public static PublicKey getPublicKey(String base64) throws Exception {// 解码Base64字符串回字节数组byte[] encodedPrivateKey = Base64.getDecoder().decode(base64);// 使用PKCS8EncodedKeySpec和KeyFactory来加载私钥//PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedPrivateKey);KeyFactory kf = KeyFactory.getInstance(RSA);PublicKey publicKey = kf.generatePublic(keySpec);return publicKey;}/*** 使用私钥对明文进行签名** @param plainText  明文* @param privateKey 私钥* @return 签名结果* @throws Exception 签名异常*/public static String sign(String plainText, PrivateKey privateKey) throws Exception {Signature signature = Signature.getInstance(SHA256WITHRSA);signature.initSign(privateKey);signature.update(plainText.getBytes());return Base64.getEncoder().encodeToString(signature.sign());}/*** 使用公钥对签名进行验证** @param plainText 明文* @param signature 签名结果* @param publicKey 公钥* @return 验证结果,true表示验证通过,false表示验证失败* @throws Exception 验证异常*/public static boolean verify(String plainText, String signature, PublicKey publicKey) throws Exception {Signature signatureInstance = Signature.getInstance(SHA256WITHRSA);signatureInstance.initVerify(publicKey);signatureInstance.update(plainText.getBytes());byte[] decodedSignature = Base64.getDecoder().decode(signature);return signatureInstance.verify(decodedSignature);}
}

使用

package com.wujialiang;/*** Hello world!*/
public class App {public static void main(String[] args) {// 生成RSA密钥对
//        KeyPair keyPair = generateKeyPair();
//        PrivateKey privateKey = keyPair.getPrivate();
//        PublicKey publicKey = keyPair.getPublic();// 公钥String pk = //"-----BEGIN PUBLIC KEY-----\n" +"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3XSdz1MnzazBEN5KOfTx0IyVJ\n" +"Z5wb57isrCuHDhnYXwtmdhQalgII0fozeeFpMpAvlnmHC1kpW7XVGvZnLx3bWbCE\n" +"bf+pMSW4kmQuI+5cxRUJbCl7sdaODBrINgERHPICVC18AJLThEVMHyjuR6Jn4zQm\n" +"yYNbReSktY/BrFTvMQIDAQAB\n"//+"-----END PUBLIC KEY-----";// 私钥String priK = //"-----BEGIN PRIVATE KEY-----\n" +"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAPddJ3PUyfNrMEQ3\n" +"ko59PHQjJUlnnBvnuKysK4cOGdhfC2Z2FBqWAgjR+jN54WkykC+WeYcLWSlbtdUa\n" +"9mcvHdtZsIRt/6kxJbiSZC4j7lzFFQlsKXux1o4MGsg2AREc8gJULXwAktOERUwf\n" +"KO5HomfjNCbJg1tF5KS1j8GsVO8xAgMBAAECgYEA6eG1JMrj63jEmStmMb1txG1a\n" +"mu4Q5z2QGgtr2HVXsIIlGEq6tWxyHf7TL4qkuz9onuYKn8n2Eqm44fZtVaBx+5ES\n" +"zRpIvlTvaxmVu0HZ1hYAzUw1XyRnXNMKpL5tT4GCjm8+QGPzlGxgXI1sNg8r9Jaw\n" +"9zRUYeA6LQR9RIMkHWUCQQD8QojjVoGjtiunoh/N8iplhUszZIavAEvmDIE+kVy+\n" +"pA7hvlukLw6JMc7cfTcnHyxDo9iHVIzrWlTuKRq9KWVLAkEA+wgJS2sgtldnCVn6\n" +"tJKFVwsHrWhMIU29msPPbNuWUD23BcKE/vehIyFu1ahNA/TiM40PEnzprQ5JfPxU\n" +"16S78wJANTfMLTnYy7Lo7sqTLx2BuD0wqjzw9QZ4/KVytsJv8IAn65P/PVn4FRV+\n" +"8KEx+3zmF7b/PT2nJRe/hycAzxtmlQJBAMrFwQxEqpXfoAEzx4lY2ZBn/nmaR/SW\n" +"4VNEXCbocVC7qT1j1R5HVMgV13uKiTtq8dUGWmhqsi7x3XayNK5ECPUCQQDZaAN6\n" +"tvIHApz9OLsXSw0jZirQ6KEYdharXbIVDy1W1sVE3lzLbqLdFp1bxAHQIvsYS5PM\n" +"A9veSJh372RLJKkj\n"//+"-----END PRIVATE KEY-----";// 明文String src = "好厉害";src ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiMTU2MjEzNTc1MDEiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ4MDY5NjUyNDQ4NDY3NyIsImh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd3MvMjAwOC8wNi9pZGVudGl0";//私钥签名String c = null;try {c = SHA256withRSAUtil.sign(src, SHA256withRSAUtil.getPrivateKey(priK.replace("\n","")));System.out.println(c);//公钥验签(true表示验证通过,false表示验证失败)System.out.println("验证结果:" + SHA256withRSAUtil.verify(src, c, SHA256withRSAUtil.getPublicKey(pk.replace("\n",""))));} catch (Exception e) {throw new RuntimeException(e);}}
}

在这里插入图片描述

可以看到java加签和C#、js加签结果一样,所以验签也是通过的

参考

rsa js和java互通
C# rsa加签验签

相关文章:

  • 【MYSQL】解决数据库Too many connections
  • 前端菜鸡学习日记 -- 关于pnpm
  • kakfa发版丢消息事件分析
  • CRMEB Pro版高并发商城系统秒杀需要多大的服务器
  • [Linux内核驱动]模块参数
  • 【开源项目】智慧北京案例~超经典实景三维数字孪生智慧城市CIM/BIM数字孪生可视化项目——开源工程及源码!
  • redis之集群
  • Python web 开发 flask 实践
  • 汇凯金业:现货黄金投资平仓策略有哪些
  • 暴雨讲堂|通往AGI的必由之路—AI agent是什么?
  • 超详细的linux-conda环境安装教程
  • svm 超参数
  • maxwell源码编译安装部署
  • Docker 从安装到使用的完整指南
  • Python抓取高考网图片
  • 【技术性】Search知识
  • create-react-app做的留言板
  • GraphQL学习过程应该是这样的
  • Javascript设计模式学习之Observer(观察者)模式
  • Java多线程(4):使用线程池执行定时任务
  • JS实现简单的MVC模式开发小游戏
  • mysql 5.6 原生Online DDL解析
  • Redux 中间件分析
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • 初识 webpack
  • 关于字符编码你应该知道的事情
  • 坑!为什么View.startAnimation不起作用?
  • 微服务框架lagom
  • 学习笔记TF060:图像语音结合,看图说话
  • 一个SAP顾问在美国的这些年
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #### golang中【堆】的使用及底层 ####
  • #android不同版本废弃api,新api。
  • (2022 CVPR) Unbiased Teacher v2
  • (C语言)编写程序将一个4×4的数组进行顺时针旋转90度后输出。
  • (二)斐波那契Fabonacci函数
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (附源码)计算机毕业设计ssm基于B_S的汽车售后服务管理系统
  • (南京观海微电子)——COF介绍
  • (七)Appdesigner-初步入门及常用组件的使用方法说明
  • (四)opengl函数加载和错误处理
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • (一)WLAN定义和基本架构转
  • (原创)攻击方式学习之(4) - 拒绝服务(DOS/DDOS/DRDOS)
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • **PHP二维数组遍历时同时赋值
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .libPaths()设置包加载目录
  • .Net - 类的介绍
  • .net 7 上传文件踩坑
  • .NET MAUI Sqlite数据库操作(二)异步初始化方法
  • .net 无限分类
  • .NET开源、简单、实用的数据库文档生成工具
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验