java sha256withrsa_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("") + 9, privateKeyXml.indexOf(""));

BigInteger modulus = new BigInteger(1, Base64.getDecoder().decode(modulusXml));

String publicExponentXml = privateKeyXml.substring(privateKeyXml.indexOf("") + 10, privateKeyXml.indexOf(""));

BigInteger publicExponent = new BigInteger(1, Base64.getDecoder().decode(publicExponentXml));

String privateExponentXml = privateKeyXml.substring(privateKeyXml.indexOf("") + 3, privateKeyXml.indexOf(""));

BigInteger privateExponent = new BigInteger(1, Base64.getDecoder().decode(privateExponentXml));

String primePXml = privateKeyXml.substring(privateKeyXml.indexOf("

") + 3, privateKeyXml.indexOf("

"));

BigInteger primeP = new BigInteger(1, Base64.getDecoder().decode(primePXml));

String primeQXml = privateKeyXml.substring(privateKeyXml.indexOf("") + 3, privateKeyXml.indexOf(""));

BigInteger primeQ = new BigInteger(1, Base64.getDecoder().decode(primeQXml));

String primeExponentPXml = privateKeyXml.substring(privateKeyXml.indexOf("") + 4, privateKeyXml.indexOf(""));

BigInteger primeExponentP = new BigInteger(1, Base64.getDecoder().decode(primeExponentPXml));

String primeExponentQXml = privateKeyXml.substring(privateKeyXml.indexOf("") + 4, privateKeyXml.indexOf(""));

BigInteger primeExponentQ = new BigInteger(1, Base64.getDecoder().decode(primeExponentQXml));

String crtCoefficientXml = privateKeyXml.substring(privateKeyXml.indexOf("") + 10, privateKeyXml.indexOf(""));

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("") + 9, publicKeyXml.indexOf(""));

BigInteger modulus = new BigInteger(1, Base64.getDecoder().decode(modulusXml));

String exponentXml = publicKeyXml.substring(publicKeyXml.indexOf("") + 10, publicKeyXml.indexOf(""));

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("\n");

stringBuilder.append("").append(modulus).append("\n");

stringBuilder.append("").append(exponent).append("\n");

stringBuilder.append("

").append(p).append("

\n");

stringBuilder.append("").append(q).append("\n");

stringBuilder.append("").append(dp).append("\n");

stringBuilder.append("").append(dq).append("\n");

stringBuilder.append("").append(inverseQ).append("\n");

stringBuilder.append("").append(d).append("\n");

stringBuilder.append("");

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("\n");

stringBuilder.append("").append(modulus).append("\n");

stringBuilder.append("").append(exponent).append("\n");

stringBuilder.append("");

return stringBuilder.toString();

}

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);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值