.NET和Java中的密钥
ASN.1、PKCS是最初的,也是最主要的RSA公钥和私钥的语法标准,被RSA Lab所维护。
ASN.1、PKCS#1都定义了公钥和私钥的类型——序列化的数字。为了下一个层次的抽象(适当的包装),现在一般使用的组合是:PKCS#8的私钥,X.509的公钥 。
PKCS语法主要用于私钥,其内部标准目前有10种。目前JAVA普遍使用的是PKCS#8,用作私钥格式。
X.509语法主要用于公钥,广泛使用于web浏览器和SLL。
3种语法标准的公私钥可以实现相互转化,其核心为ASN1语法中的整数值(modulus,PublicExponent,privateExponent ),其余的数值都可以经过计算后得出。
.NET使用的是标准的RSA格式,然后将其中的数字base64编码后,生成XML进行存储。
java中使用的是PKCS#8,、X.509的公私钥语法,存储的都是相应的JAVA类自动生成的base64字符串。
由于存储格式的区别,在相互转换、读取的时候,需要理解RSA相关的知识,才能正确使用类来转换。
密钥格式
c#公钥:
<RSAKeyValue><Modulus>yuSIL2dWBUJbtEItaHKCBTJ28lQJyIql4+Ptu5kcjnCYOy5Z/FOzLoq4htyuH5Z1JamU+9IbZG5+hmR7St7hLvByJaK4Xkqw23amJOv5GvqoEieB0pf8Fp96WgIoYrNP/85Q8Rkltn9/16bLn0LI6WQNTb0S85wAHokNoi4/OhM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
c#私钥:
<RSAKeyValue><Modulus>yuSIL2dWBUJbtEItaHKCBTJ28lQJyIql4+Ptu5kcjnCYOy5Z/FOzLoq4htyuH5Z1JamU+9IbZG5+hmR7St7hLvByJaK4Xkqw23amJOv5GvqoEieB0pf8Fp96WgIoYrNP/85Q8Rkltn9/16bLn0LI6WQNTb0S85wAHokNoi4/OhM=</Modulus><Exponent>AQAB</Exponent><P>6YS3ZIEclzPX43CaX/ssaouHwUDpnL9dBfrHZs/YxjQS8KNtgl9H+kD3Thc+rl5wIyLPWeKFFiBJuRmziKkQjQ==</P><Q>3m0D/eebwUIcA93Kdu934hwmjxuxInD+iEKrLpMweQLSF5EkIHvkeFZkRc6xs0Hfjq960eJmTcfj+tE42I9dHw==</Q><DP>RAC3G1iSB+I8E2q+Ogc+JwTdEsUhgtkjcNNX8DPE7+tIPLWK9XVj05fJrP8N7N9pjoHbmlRh51Cdx36ZjsmVHQ==</DP><DQ>JRsAoHnj1PCnZcm5PfAjCrhxgkw3V6yL+cVNc16gpn9e9wmCglzIt36KCc86e9IQbmg90Ae50132XWBL4GzCNw==</DQ><InverseQ>nM8lxawgzM5kjXU7u8VpHFHpZ3ZdPZ7EVsHjnxBST4mt1LMW6hsQe8OQYzP0qH999+97P8q1RZ1oyQwRrrZK9g==</InverseQ><D>Kc2iXZn9+EFu4ZoM/wswzN9T8KPuDBq9CVJKBjAK2TJLu03Wjo20Sm+ci3Tmj22Rn3vsTWJB8JRvj0MewBNh88r3gmzTvE5HYrR/EP2FqGA7hlaqvXH2sAliMhCQLNkl3wVYjTazLvRv5jiCiGCt29UEIb0LhdgA3scbSrf+oZk=</D></RSAKeyValue>
java公钥:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOIakky8cbDGZCvoiHfmvb7nxpd8h/gxydvmAmAPyAzHH9Ij+aKRjukdxcPawnci4WpfUBaUlnhTbpDkyqjcYy/h/iabFGxW7MYV4cdsH2ilw7dUQyDSeDNozw7AjW4f1yNuMiFKDWOwXFz7I/qJkTQraVn1+AO3ZTezU5+2HrHwIDAQAB
java私钥:
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAI4hqSTLxxsMZkK+iId+a9vufGl3yH+DHJ2+YCYA/IDMcf0iP5opGO6R3Fw9rCdyLhal9QFpSWeFNukOTKqNxjL+H+JpsUbFbsxhXhx2wfaKXDt1RDINJ4M2jPDsCNbh/XI24yIUoNY7BcXPsj+omRNCtpWfX4A7dlN7NTn7YesfAgMBAAECgYB0hoBH3JGWSWolWlRQ0YLYQwPY7A2DDRkO8p+dSL27UuI5aDTAzOTV4tvI+/8CMAg9JT5jM9CsgHjuRXzxb16IAhD/cZxWTHyyrtcSB6vaby88i9mGx7N1wxhDj4Rh7PfrI95siV/uszrL0CGJY6uN3zVUbs7IgkT8qPRFeR36cQJBAM+JYQDXCZFT8vv2wgDOkHle4EQbj/S3oefvMuYV97KXjgnku79SIxABvTyQMtulwNux22T8CaxM6sEVaISD480CQQCvUlYiicGp/CZ6uyhrdbMQ+OD5zb3KcKKt1MKlWiuS35F2xTQ4c3QPhGBX1hrqwMqF4KlSn/UQGk9+g+GtIPabAkArJxqXbR8dK8J7Z6yhNFJQGk0xfDWrob81lcQUmX6+kMrE/d2YA4Es49+wRx98EnQOemXvEoUEYZ3ydfwcibwFAkAZO2haIClXJYsELttqW84hqy/1w76E3CENk4lP8uJCiRqOVWNmnHcfpJWZDp9hGc4L5oF3+r1yS9cVBjX8jLnxAkEAiwFXB74VCWDns85ARG2XPgzKXl+cnUwTWoMxvPLDy7AbuNpPRM1NIc2R/ISH7qRNcAWi5DD+VoVsGYHkZQ0+XA==
很明显他们的格式是不同的。
现在需求是这样的使用java将公钥发出去,.net使用公钥加密,然后java再解密。
先把java的加密方法放出来:
package com.mantishell;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
public class TestRsa {
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 获取密钥对
*
* @return 密钥对
*/
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
return generator.generateKeyPair();
}
/**
* 获取私钥
*
* @param privateKey 私钥字符串
* @return
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
}
/**
* 获取公钥
*
* @param publicKey 公钥字符串
* @return
*/
public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
}
/**
* RSA加密
*
* @param data 待加密数据
* @param publicKey 公钥
* @return
*/
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.getBytes().length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
// 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
// 加密后的字符串
return new String(Base64.encodeBase64String(encryptedData));
}
/**
* RSA解密
*
* @param data 待解密数据
* @param privateKey 私钥
* @return
*/
public static String decrypt(String data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的内容
return new String(decryptedData, "UTF-8");
}
/**
* 签名
*
* @param data 待签名数据
* @param privateKey 私钥
* @return 签名
*/
public static String sign(String data, PrivateKey privateKey) throws Exception {
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.encodeBase64(signature.sign()));
}
/**
* 验签
*
* @param srcData 原始字符串
* @param publicKey 公钥
* @param sign 签名
* @return 是否验签通过
*/
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
public static void main(String[] args) throws Exception{
TestSimple();
}
public static void TestSimple(){
try {
// 生成密钥对
KeyPair keyPair = getKeyPair();
String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
System.out.println("私钥:" + privateKey);
System.out.println("公钥:" + publicKey);
// RSA加密
String data = "待加密的文字内容";
String encryptData = encrypt(data, getPublicKey(publicKey));
System.out.println("加密后内容:" + encryptData);
// RSA解密
String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
System.out.println("解密后内容:" + decryptData);
// RSA签名
String sign = sign(data, getPrivateKey(privateKey));
// RSA验签
boolean result = verify(data, getPublicKey(publicKey), sign);
System.out.print("验签结果:" + result);
} catch (Exception e) {
e.printStackTrace();
System.out.print("加解密异常");
}
}
}
这里需要添加一下maven的坐标:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
现在生成的公钥就是这么一串字符串:
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOIakky8cbDGZCvoiHfmvb7nxpd8h/gxydvmAmAPyAzHH9Ij+aKRjukdxcPawnci4WpfUBaUlnhTbpDkyqjcYy/h/iabFGxW7MYV4cdsH2ilw7dUQyDSeDNozw7AjW4f1yNuMiFKDWOwXFz7I/qJkTQraVn1+AO3ZTezU5+2HrHwIDAQAB
Java公钥转为C#公钥(C#代码)
C#中的公私钥使用XML字符串进行存储,读取时直接读入字符串即可。
由于C#使用的是标准的RSA格式,因此JAVA的RSAPublicKeySpec、RSAPrivateKeySpec配置类的核心参数(modulus,PublicExponent,privateExponent )都可以从对应XML中的节点值(Modulus-modulus 、Exponent-PublicExponent 、D-privateExponent )base64解码后获取。然后将其传入JAVA配置类中,然后根据配置类生成相应的RSA公私钥。
客户端.net平台下如何操作呢?
需要安装BouncyCastle包。
首先需要将公钥转换成.net平台认识的格式:
var keyStr = CryptoHelper.RsaPublicKeyJava2DotNet(publicKeyStr);//publicKeyStr就是公钥,返回.net平台认识的RSA公钥格式
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
//上面两句引用必不可少
/// <summary>
/// RSA公钥格式转换,java->.net
/// </summary>
/// <param name="publicKey">java生成的公钥</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()));
}
//还不能少了package
<package id="BouncyCastle" version="1.8.5" targetFramework="net45" />
转换完成后,将传送的字符串进行加密处理:
/// <summary>
/// RSA加密 将公钥导入到RSA对象中,准备加密
/// </summary>
/// <param name="publicKey">公钥</param>
/// <param name="encryptstring">待加密的字符串</param>
public static string RsaEncrypt(string publicKey, string encryptstring)
{
using (var rsaProvider = new RSACryptoServiceProvider())
{
var inputBytes = Encoding.UTF8.GetBytes(encryptstring);//有含义的字符串转化为字节流
rsaProvider.FromXmlString(publicKey);//载入公钥
int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度
var buffer = new byte[bufferSize];
using (MemoryStream inputStream = new MemoryStream(inputBytes),outputStream = new MemoryStream())
{
while (true)
{ //分段加密
int readSize = inputStream.Read(buffer, 0, bufferSize);
if (readSize <= 0)
{
break;
}
var temp = new byte[readSize];
Array.Copy(buffer, 0, temp, 0, readSize);
var encryptedBytes = rsaProvider.Encrypt(temp, false);
outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
}
return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输
}
}
}
分段加密是因为数据多的话,报“不正确的长度”的异常。
然后使用C#语言加密,加密完成后,把加密后的字符串给java平台去解密即可,java拿加密后的字符串和存储的私钥进行解密即可得到明文。
下面是两个类:
RsaHelper.cs
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
/// <summary>
/// 生成密钥
/// <param name="privateKey">私钥</param>
/// <param name="publicKey">公钥</param>
/// <param name="keySize">密钥长度:512,1024,2048,4096,8192</param>
/// </summary>
public static void Generator(out string privateKey, out string publicKey, int keySize = 1024)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(keySize);
privateKey = rsa.ToXmlString(true); //将RSA算法的私钥导出到字符串PrivateKey中 参数为true表示导出私钥 true 表示同时包含 RSA 公钥和私钥;false 表示仅包含公钥。
publicKey = rsa.ToXmlString(false); //将RSA算法的公钥导出到字符串PublicKey中 参数为false表示不导出私钥 true 表示同时包含 RSA 公钥和私钥;false 表示仅包含公钥。
}
/// <summary>
/// RSA加密 将公钥导入到RSA对象中,准备加密
/// </summary>
/// <param name="publicKey">公钥</param>
/// <param name="encryptstring">待加密的字符串</param>
public static string RsaEncrypt(string publicKey, string encryptstring)
{
using (var rsaProvider = new RSACryptoServiceProvider())
{
var inputBytes = Encoding.UTF8.GetBytes(encryptstring);//有含义的字符串转化为字节流
rsaProvider.FromXmlString(publicKey);//载入公钥
int bufferSize = (rsaProvider.KeySize / 8) - 11;//单块最大长度
var buffer = new byte[bufferSize];
using (MemoryStream inputStream = new MemoryStream(inputBytes),outputStream = new MemoryStream())
{
while (true)
{ //分段加密
int readSize = inputStream.Read(buffer, 0, bufferSize);
if (readSize <= 0)
{
break;
}
var temp = new byte[readSize];
Array.Copy(buffer, 0, temp, 0, readSize);
var encryptedBytes = rsaProvider.Encrypt(temp, false);
outputStream.Write(encryptedBytes, 0, encryptedBytes.Length);
}
return Convert.ToBase64String(outputStream.ToArray());//转化为字节流方便传输
}
}
}
CryptoHelper.cs
using System;
using System.IO;
using System.Security.Cryptography;
using System.Xml;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
/// <summary>
/// RSA密钥转Pem密钥
/// </summary>
/// <param name="RSAKey">RSA密钥</param>
/// <param name="isPrivateKey">是否是私钥</param>
/// <returns>Pem密钥</returns>
public static string RsaKeyToPem(string RSAKey, bool isPrivateKey)
{
string pemKey = string.Empty;
var rsa = new RSACryptoServiceProvider();
rsa.FromXmlString(RSAKey);
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();
}
return pemKey;
}
/// <summary>
/// Pem密钥转RSA密钥
/// </summary>
/// <param name="pemKey">Pem密钥</param>
/// <param name="isPrivateKey">是否是私钥</param>
/// <returns>RSA密钥</returns>
public static string PemToRsaKey(string pemKey, bool isPrivateKey = false)
{
string rsaKey = string.Empty;
object pemObject = null;
RSAParameters rsaPara = new RSAParameters();
using (StringReader sReader = new StringReader(pemKey))
{
var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(sReader);
pemObject = pemReader.ReadObject();
}
//RSA私钥
if (isPrivateKey)
{
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(),
};
}
//RSA公钥
else
{
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;
}
/// <summary>
/// RSA私钥格式转换,java->.net
/// </summary>
/// <param name="privateKey">java生成的RSA私钥</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>
/// RSA私钥格式转换,.net->java
/// </summary>
/// <param name="privateKey">.net生成的私钥</param>
/// <returns></returns>
public static string RsaPrivateKeyDotNet2Java(string privateKey)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(privateKey);
if (doc.DocumentElement == null)
{
return null;
}
BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
BigInteger exp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
BigInteger d = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("D")[0].InnerText));
BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("P")[0].InnerText));
BigInteger q = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Q")[0].InnerText));
BigInteger dp = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DP")[0].InnerText));
BigInteger dq = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("DQ")[0].InnerText));
BigInteger qinv = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("InverseQ")[0].InnerText));
RsaPrivateCrtKeyParameters privateKeyParam = new RsaPrivateCrtKeyParameters(m, exp, d, p, q, dp, dq, qinv);
PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKeyParam);
byte[] serializedPrivateBytes = privateKeyInfo.ToAsn1Object().GetEncoded();
return Convert.ToBase64String(serializedPrivateBytes);
}
/// <summary>
/// RSA公钥格式转换,java->.net
/// </summary>
/// <param name="publicKey">java生成的公钥</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公钥格式转换,.net->java
/// </summary>
/// <param name="publicKey">.net生成的公钥</param>
/// <returns></returns>
public static string RsaPublicKeyDotNet2Java(string publicKey)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(publicKey);
if (doc.DocumentElement == null)
{
return null;
}
BigInteger m = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Modulus")[0].InnerText));
BigInteger p = new BigInteger(1, Convert.FromBase64String(doc.DocumentElement.GetElementsByTagName("Exponent")[0].InnerText));
RsaKeyParameters pub = new RsaKeyParameters(false, m, p);
SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub);
byte[] serializedPublicBytes = publicKeyInfo.ToAsn1Object().GetDerEncoded();
return Convert.ToBase64String(serializedPublicBytes);
}