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