RSA加密之C#格式与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  />

转换完成后,将传送的字符串进行加密处理:

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