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 这里复现一下完整过程: 安 ...
随机推荐
- Centos7 手动编译 RabbitMQ ,并安装php amqp
RabbitMQ是一个在AMQP基础上完成的,可复用的企业消息系统,底层基于Erlang语言. 一:centos7安装RabbitMQ 这玩意儿安装很扯淡,官方推荐rpm安装,rpm安装本身是最简单的 ...
- IIS7(Windows7)下最简单最强安装多版本PHP支持环境
最近调试程序,要在PHP5.2和5.3之间换来换去,而习惯了windows下的开发,就琢磨怎么在iis下安装多版本支持,赫然发现其实微软都为我们准备了好工具. 微软对PHP的支持越来越强,这点在IIS ...
- Python爬虫-爬取豆瓣图书Top250
豆瓣网站很人性化,对于新手爬虫比较友好,没有如果调低爬取频率,不用担心会被封 IP.但也不要太频繁爬取. 涉及知识点:requests.html.xpath.csv 一.准备工作 需要安装reques ...
- php+memcache高速缓存
原文地址:https://blog.csdn.net/qq_33571752/article/details/86494667 #在lnmp基础上修改 依赖libevent程序库 cd lnmp/ta ...
- Kubernetes环境部署
简介 Kubernetes 是一个开源系统,用于容器化应用的自动部署.扩缩和管理.它将构成应用的容器按逻辑单位进行分组以便于管理和发现. 配置镜像源 Debian / Ubuntu apt-get ...
- Java IO把一个文件中的内容以字符串的形式读出来
代码记录(备查): /** * 把一个文件中的内容以字符串的形式读出来 * * @author zhipengs * */ public class FileToString { public sta ...
- nodejs ffi 调用dll
安装依赖 npm install --global --production windows-build-tools(在管理员权限打开的命令行中执行) npm install -g node-gyp ...
- JIRA+JIRA Agile敏捷项目管理工具
jira插件下载地址 http://www.confluence.cn/pages/viewpage.action?pageId=1671327 下载GreenHopper插件 安装Jira-agil ...
- [C语言]给定直角三角形面积和斜边长
[A题] 翘课的HugeGun_ 时间限制:1000ms 内存限制:65536kb 题目描述 HugeGun学姐很喜欢翘课.不幸的是,这一次她被发现了. 老师让她打扫了教室.当她把扫把靠在墙上 ...
- 最小二乘求解常数k使得kx=y(x,y为列向量)
直接求解法 取范数 \[ E(k)=\|kx-y\|^{2}\\ \] 构建最小二乘得出 \[ \arg \min (E(k))=k^2x^Tx+y^Ty-2x^Tyk \] 对k求导有 \[ 2x^ ...