SHA256WithRSA
在上文中了解到SHA和RSA,工作中恰好用到扩展应用:SHA256WithRSA,本文总结下学习过程,备忘の
再提供另外一种方法,实现Java版pem密钥和.Net版xml密钥相互转换的方法
密钥转换
- RSA密钥:Pem --> XML
public static string RSAKeyPemToXml(string pemKey, bool isPrivateKey)
{
string rsaKey = string.Empty;
object pemObject = null;
RSAParameters rsaPara = new RSAParameters();
using (var sReader = new StringReader(pemKey)) {
var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sReader);
pemObject = pemReader.ReadObject();//(AsymmetricCipherKeyPair)
}
if (isPrivateKey)//RSA私钥
{
RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)((AsymmetricCipherKeyPair)pemObject).Private;
rsaPara = new RSAParameters {
Modulus = key.Modulus.ToByteArrayUnsigned(),
Exponent = key.PublicExponent.ToByteArrayUnsigned(),
D = key.Exponent.ToByteArrayUnsigned(),
P = key.P.ToByteArrayUnsigned(),
Q = key.Q.ToByteArrayUnsigned(),
DP = key.DP.ToByteArrayUnsigned(),
DQ = key.DQ.ToByteArrayUnsigned(),
InverseQ = key.QInv.ToByteArrayUnsigned(), };
}
else//RSA公钥
{
RsaKeyParameters key = (RsaKeyParameters)pemObject;
rsaPara = new RSAParameters {
Modulus = key.Modulus.ToByteArrayUnsigned(),
Exponent = key.Exponent.ToByteArrayUnsigned(), };
}
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaPara);
using (StringWriter sw = new StringWriter()) {
sw.Write(rsa.ToXmlString(isPrivateKey ? true : false));
rsaKey = sw.ToString();
}
return rsaKey;
}
- RSA密钥:XML --> Pem
public static string RSAKeyXmlToPem(string RSAKeyXml, bool isPrivateKey, bool replacefix)
{
string pemKey = string.Empty;
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(RSAKeyXml);
RSAParameters rsaPara = new RSAParameters();
RsaKeyParameters key = null;
//RSA私钥
if (isPrivateKey) {
rsaPara = rsa.ExportParameters(true);
key = new RsaPrivateCrtKeyParameters(
new BigInteger(1, rsaPara.Modulus), new BigInteger(1, rsaPara.Exponent), new BigInteger(1, rsaPara.D),
new BigInteger(1, rsaPara.P), new BigInteger(1, rsaPara.Q), new BigInteger(1, rsaPara.DP), new BigInteger(1, rsaPara.DQ),
new BigInteger(1, rsaPara.InverseQ));
}
//RSA公钥
else {
rsaPara = rsa.ExportParameters(false);
key = new RsaKeyParameters(false,
new BigInteger(1, rsaPara.Modulus), new BigInteger(1, rsaPara.Exponent));
}
using (TextWriter sw = new StringWriter()) {
var pemWriter = new Org.BouncyCastle.OpenSsl.PemWriter(sw);
pemWriter.WriteObject(key);
pemWriter.Writer.Flush();
pemKey = sw.ToString();
}
if (replacefix) {
//去掉证书的头部和尾部
pemKey = isPrivateKey ? pemKey.Replace("-----BEGIN RSA PRIVATE KEY-----", "").Replace("-----END RSA PRIVATE KEY-----", "") :
pemKey.Replace("-----BEGIN PUBLIC KEY-----", "").Replace("-----END PUBLIC KEY-----", "");
return pemKey.Replace("\n", "").Replace("\r", "");
}
else { return pemKey; }
}
注意,调用RSAKeyPemToXml()方法时,pemKey必须格式正确(带前后缀且换行),否则调用报错。
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
此外,调用RSAKeyXmlToPem()方法做私钥转换时,结果与原Pem密钥不一致,慎用。
密钥转换(java)
- 公钥:X.509 pem,Java:X509EncodedKeySpec
- 私钥:PKCS#8 pem,Java:PKCS8EncodedKeySpec
/**
* C#私钥转换成java私钥
*/
public static String privateKeyFromXml(String privateKeyXml) {
privateKeyXml = privateKeyXml.replaceAll("\r", "").replaceAll("\n", "");
KeyFactory keyFactory;
try {
String modulusXml = privateKeyXml.substring(privateKeyXml.indexOf("<Modulus>") + 9, privateKeyXml.indexOf("</Modulus>"));
BigInteger modulus = new BigInteger(1, Base64.getDecoder().decode(modulusXml));
String publicExponentXml = privateKeyXml.substring(privateKeyXml.indexOf("<Exponent>") + 10, privateKeyXml.indexOf("</Exponent>"));
BigInteger publicExponent = new BigInteger(1, Base64.getDecoder().decode(publicExponentXml));
String privateExponentXml = privateKeyXml.substring(privateKeyXml.indexOf("<D>") + 3, privateKeyXml.indexOf("</D>"));
BigInteger privateExponent = new BigInteger(1, Base64.getDecoder().decode(privateExponentXml));
String primePXml = privateKeyXml.substring(privateKeyXml.indexOf("<P>") + 3, privateKeyXml.indexOf("</P>"));
BigInteger primeP = new BigInteger(1, Base64.getDecoder().decode(primePXml));
String primeQXml = privateKeyXml.substring(privateKeyXml.indexOf("<Q>") + 3, privateKeyXml.indexOf("</Q>"));
BigInteger primeQ = new BigInteger(1, Base64.getDecoder().decode(primeQXml));
String primeExponentPXml = privateKeyXml.substring(privateKeyXml.indexOf("<DP>") + 4, privateKeyXml.indexOf("</DP>"));
BigInteger primeExponentP = new BigInteger(1, Base64.getDecoder().decode(primeExponentPXml));
String primeExponentQXml = privateKeyXml.substring(privateKeyXml.indexOf("<DQ>") + 4, privateKeyXml.indexOf("</DQ>"));
BigInteger primeExponentQ = new BigInteger(1, Base64.getDecoder().decode(primeExponentQXml));
String crtCoefficientXml = privateKeyXml.substring(privateKeyXml.indexOf("<InverseQ>") + 10, privateKeyXml.indexOf("</InverseQ>"));
BigInteger crtCoefficient = new BigInteger(1, Base64.getDecoder().decode(crtCoefficientXml));
RSAPrivateCrtKeySpec rsaPriKey = new RSAPrivateCrtKeySpec(modulus, publicExponent, privateExponent, primeP, primeQ, primeExponentP, primeExponentQ, crtCoefficient);
keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(rsaPriKey);
byte[] bytes = Base64.getEncoder().encode(privateKey.getEncoded());
return new String(bytes, Charset.forName("utf-8"));
} catch (Exception e) {
System.err.println(e.toString());
}
return null;
}
/**
* C#公钥转换成java公钥
*/
public static String publicKeyFromXml(String publicKeyXml) {
KeyFactory keyFactory;
publicKeyXml = publicKeyXml.replaceAll("\r", "").replaceAll("\n", "");
try {
String modulusXml = publicKeyXml.substring(publicKeyXml.indexOf("<Modulus>") + 9, publicKeyXml.indexOf("</Modulus>"));
BigInteger modulus = new BigInteger(1, Base64.getDecoder().decode(modulusXml));
String exponentXml = publicKeyXml.substring(publicKeyXml.indexOf("<Exponent>") + 10, publicKeyXml.indexOf("</Exponent>"));
BigInteger publicExponent = new BigInteger(1, Base64.getDecoder().decode(exponentXml));
RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulus, publicExponent);
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(rsaPubKey);
byte[] bytes = Base64.getEncoder().encode(publicKey.getEncoded());
return new String(bytes, Charset.forName("utf-8"));
} catch (Exception e) {
System.err.println(e.toString());
return null;
}
}
/**
* java私钥转换成C#私钥
*/
public static String privateKeyToXml(RSAPrivateCrtKey privateKey) {
String modulusBase64 = Base64.getEncoder().encodeToString(privateKey.getModulus().toByteArray());
String modulus = modulusBase64.replace("\r", "").replace("\n", "");
String exponentBase64 = Base64.getEncoder().encodeToString(privateKey.getPublicExponent().toByteArray());
String exponent = exponentBase64.replace("\r", "").replace("\n", "");
String pBase64 = Base64.getEncoder().encodeToString(privateKey.getPrimeP().toByteArray());
String p = pBase64.replace("\r", "").replace("\n", "");
String qBase64 = Base64.getEncoder().encodeToString(privateKey.getPrimeQ().toByteArray());
String q = qBase64.replace("\r", "").replace("\n", "");
String dpBase64 = Base64.getEncoder().encodeToString(privateKey.getPrimeExponentP().toByteArray());
String dp = dpBase64.replace("\r", "").replace("\n", "");
String dqBase64 = Base64.getEncoder().encodeToString(privateKey.getPrimeExponentQ().toByteArray());
String dq = dqBase64.replace("\r", "").replace("\n", "");
String dBase64 = Base64.getEncoder().encodeToString(privateKey.getPrivateExponent().toByteArray());
String d = dBase64.replace("\r", "").replace("\n", "");
String inverseQBase64 = Base64.getEncoder().encodeToString(privateKey.getCrtCoefficient().toByteArray());
String inverseQ = inverseQBase64.replace("\r", "").replace("\n", "");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<RSAKeyValue>\n");
stringBuilder.append("<Modulus>").append(modulus).append("</Modulus>\n");
stringBuilder.append("<Exponent>").append(exponent).append("</Exponent>\n");
stringBuilder.append("<P>").append(p).append("</P>\n");
stringBuilder.append("<Q>").append(q).append("</Q>\n");
stringBuilder.append("<DP>").append(dp).append("</DP>\n");
stringBuilder.append("<DQ>").append(dq).append("</DQ>\n");
stringBuilder.append("<InverseQ>").append(inverseQ).append("</InverseQ>\n");
stringBuilder.append("<D>").append(d).append("</D>\n");
stringBuilder.append("</RSAKeyValue>");
return stringBuilder.toString();
}
/**
* java公钥转换成C#公钥
*/
public static String publicKeyToXml(RSAPublicKey publicKey) {
String modulusBase64 = Base64.getEncoder().encodeToString(publicKey.getModulus().toByteArray());
String modulus = modulusBase64.replace("\r", "").replace("\n", "");
String exponentBase64 = Base64.getEncoder().encodeToString(publicKey.getPublicExponent().toByteArray());
String exponent = exponentBase64.replace("\r", "").replace("\n", "");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<RSAKeyValue>\n");
stringBuilder.append("<Modulus>").append(modulus).append("</Modulus>\n");
stringBuilder.append("<Exponent>").append(exponent).append("</Exponent>\n");
stringBuilder.append("</RSAKeyValue>");
return stringBuilder.toString();
}
详见:C#-Java密钥转换
pfx证书
- PFX证书:由Public Key Cryptography Standards #12,PKCS#12标准定义,包含公钥和私钥的二进制格式的证书形式,以pfx作为证书文件后缀名
- CER证书:证书中没有私钥,DER编码二进制格式的证书文件/BASE64编码格式的证书文件,以cer作为证书文件后缀名
综上所述:pfx证书文件中比cer文件中多了私钥。
通过pfx证书实现数据签名和验签
public static string Sign(string dataForSign, string priKeyFile, string keyPwd)
{
var rsa = GetPrivateKey(priKeyFile, keyPwd);
// Create a new RSACryptoServiceProvider
var rsaClear = new RSACryptoServiceProvider();
// Export RSA parameters from 'rsa' and import them into 'rsaClear'
var paras = rsa.ExportParameters(true);
rsaClear.ImportParameters(paras);
using (var sha256 = new SHA256CryptoServiceProvider()) {
var signData = rsaClear.SignData(Encoding.UTF8.GetBytes(dataForSign), sha256);
return BytesToHex(signData);
}
}
public bool VerifySign(string dataForSign, string signedData, string pubKeyFile)
{
var rsa = GetPublicKey(pubKeyFile);
using (var sha256 = new SHA256CryptoServiceProvider()) {
return rsa.VerifyData(Encoding.UTF8.GetBytes(dataForSign), sha256, HexToBytes(signedData));
}
}
其中,从.pfx证书中提取公钥和私钥的方法
private static RSACryptoServiceProvider GetPrivateKey(string priKeyFile, string keyPwd) {
var pc = new X509Certificate2(priKeyFile, keyPwd,
X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
return (RSACryptoServiceProvider)pc.PrivateKey; //return cert.PrivateKey.ToXmlString(true);
}
private static RSACryptoServiceProvider GetPublicKey(string pubKeyFile) {
var pc = new X509Certificate2(pubKeyFile);
return (RSACryptoServiceProvider)pc.PublicKey.Key; //return cert.PublicKey.Key.ToXmlString(false);
}
具体参见:.NET版SHA256WithRSA签名验签,java版本参见:java版SHA256withRSA
关于如何生成数字证书,仅供参考:方法1,方法2
该文C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密有时间可以研究下。
SHA256WithRSA的更多相关文章
- SHA256withRSA证书签名,私钥签名/公钥验签
证书签名 package test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundE ...
- Delphi支付宝支付【支持SHA1WithRSA(RSA)和SHA256WithRSA(RSA2)签名与验签】
作者QQ:(648437169) 点击下载➨Delphi支付宝支付 支付宝支付api文档 [Delphi支付宝支付]支持条码支付.扫码支付.交易查询.交易退款.退款查询.交易撤 ...
- Delphi RSA签名与验签【支持SHA1WithRSA(RSA1)、SHA256WithRSA(RSA2)和MD5WithRSA签名与验签】
作者QQ:(648437169) 点击下载➨ RSA签名与验签 [delphi RSA签名与验签]支持3种方式签名与验签(SHA1WithRSA(RSA1).SHA256WithRSA(RSA2)和M ...
- Java 签名(SHA1WithRSA、SHA256WithRSA、SHA256withECDSA)
RSA1.RSA256 签名 public static String MakeSign(String Data) { try { byte[] data = Data.getBytes(); byt ...
- Postman实现SHA256withRSA签名
@ 目录 获取pmlib 引入依赖bundle.js,有以下两种方式: 使用Pre-request Script对请求进行加签(具体加签字段请看自己项目) 获取pmlib 引入依赖bundle.js, ...
- 使用SHA256WithRSA来签名和验签(.NET/C#)
RSACryptoServiceProvider does work with SHA2-based signatures, but you have to invest some effort in ...
- C#实现SHA256WithRSA加密用于Java的秘钥私钥
首先要把Java秘钥进行转换,然后再进行加密 转制秘钥的方法 public static string RSAPrivateKeyJava2DotNet(string privateKey) { Rs ...
- Gradle 实现 Android 多渠道定制化打包
Gradle 实现 Android 多渠道定制化打包 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近在项目中遇到需要实现 Apk 多渠道.定制化打包, Google .百度查找了一些资料, ...
- spring boot启用tomcat ssl
首先要生成一个keystore证书.参考:Tomcat创建HTTPS访问,java访问https,ssl证书生成:cer&jks文件生成摘录,spring-boot 这里复现一下完整过程: 安 ...
随机推荐
- Qt编写气体安全管理系统6-地图监控
一.前言 地图监控主要是提供一个地图(可以是平面的也可以是立体彩色的,一般建议鸟瞰图,有3D感),然后设备在对应的地图上,可以切换地图来查看对应区域的设备,一般来说一个区域会有一个地图文件,设备在地图 ...
- linux记录-安装elk记录(参考博文)
什么是ELK? 通俗来讲,ELK是由Elasticsearch.Logstash.Kibana .filebeat三个开源软件的组成的一个组合体,这三个软件当中,每个软件用于完成不同的功能,ELK 又 ...
- DB2 索引(2)
最近研究了一点DB2索引相关的东西,做一个总结: (1)在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构: (2)在经常用连接的列(join)上建索引,这些列主要是一些外键,可以加快连接的速 ...
- 【转载】jmeter非GUI执行脚本+动态线程+生成HTML报告
标明文章出处: https://blog.csdn.net/qq_38915739/article/details/83018465 本次记录是在工作中为了能更好的用jmeter进行压力测试,进行 ...
- Mowing the Lawn【线性dp + 单调队列优化】
题目链接:https://ac.nowcoder.com/acm/contest/2652/G 题目大意:与上一篇博客 烽火传递 差不多. 1.一共n头羊,若超过m头连续的羊在一起,就会集体罢工,每头 ...
- English Learning -- 0611--When Burnout Is a Sign You Should Leave Your Job
I like the following article from Harvard Business Review, as I ever experienced burnout at work. Ve ...
- Cannot assign requested address的解决办法
今天想试一下redis,写了个程序,对redis连续进行100000访问,却出现以了Cannot assign requested address的问题,我起先是以为是redis的问题(可能承受不了这 ...
- quartz定时任务存储
今天不聊quartz的概念,像任务bean,触发器,调度器这些随随便便都可以百度到,其中任务bean要实现job接口.对于这些创建生成的定时任务,它可以保存在内存中,重启失效,也可以保存在数据库里重启 ...
- python 的django项目复制方法
python 的django项目复制方法 django_pyecharts_1修改为django_pyecharts_1_cs1.拷贝项目(确保原有项目是关闭状态下)2.粘贴项目并删除idea文件夹和 ...
- PAT(B) 1029 旧键盘(Java)字符串
题目链接:1029 旧键盘 (20 point(s)) 题目描述 旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及实际被输入的文字,请你列出肯定坏掉的 ...