将Java.Security.KeyPair转换为.NET RSACryptoServiceProvider

时间:2014-03-06 04:29:22

标签: java android cryptography xamarin rsa

如何对Java生成的RSA私有(和公共)密钥进行编码,以便在.NET中对其进行解码,以便在RSACryptoServiceProvider内使用?

我试过这段代码:

var keyGen = KeyPairGenerator.GetInstance("RSA");
keyGen.Initialize(2048);
KeyPair keyPair = keyGen.GenerateKeyPair();

IPrivateKey privateKey = keyPair.Private;
byte[] nativePrivateKey = privateKey.GetEncoded();

var nativeToRsa = new RSACryptoServiceProvider();
nativeToRsa.ImportCspBlob(nativePrivateKey); // throws a CryptographicException

我正在使用Xamarin.Android编写C#,但“本机”Java RSA密钥生成器 比单声道更快。所以我想使用Java,但我仍然需要能够与Windows人员交换公钥和/或私钥以与RSACryptoServiceProvider一起使用。

所以最终我可能想要/需要双向进行(Java< - > RSACryptoServiceProvider)。有没有人有任何指示?

感谢。

2 个答案:

答案 0 :(得分:1)

C#为来自RSA Crypto Provider的xml functionm加载了一个负载。尝试以下方法:

JAVA

                KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
    keyGen.initialize(1024);
    KeyPair keyPair = keyGen.generateKeyPair();
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    BigInteger mod_Int = publicKey.getModulus();
    BigInteger exp_Int = publicKey.getPublicExponent();
    byte[] mod_Bytes_Extra = mod_Int.toByteArray();
    byte[] mod_Bytes = new byte[128];
    System.arraycopy(mod_Bytes_Extra, 1, mod_Bytes, 0, 128);
    byte[] exp_Bytes = exp_Int.toByteArray();
    String modulus = Base64.encodeToString(mod_Bytes, Base64.DEFAULT);
    String exponent = Base64.encodeToString(exp_Bytes, Base64.DEFAULT);
    System.out.println(modulus);
    System.out.println(exponent);
    String public_Xml = "<BitStrength>0124</BitStrength><RSAKeyValue><Modulus>"+modulus+"</Modulus><Exponent>"+exponent+"</Exponent></RSAKeyValue>";

C#

class KeyBuilder
    {
        private RSACryptoServiceProvider rsa;

        public RSACryptoServiceProvider CreateKey(string rsaKeyPair)
        {
            rsa = new RSACryptoServiceProvider();
            StringBuilder output = new StringBuilder();
            string xmlString = "<Key>" + rsaKeyPair + "</Key>";
            rsa.FromXmlString(xmlString);
            return rsa;
        }
    }

始终让您在java端使用UTF-8编码读/写字节数组,因为Java默认使用Unicode编码,而C#使用UTF-8。

java中的字节数组也是有符号的,而在C#中它们是无符号的。因此,如果你必须解析从C#端的Java代码发送的二进制数据,请在sbyte数组中读取它。

答案 1 :(得分:1)

我在PvkConvert.java文件中找到了答案,我将其作为C#重写(在相关部分中),用于Xamarin.Android应用程序PvkConvert.cs

我了解到RSACryptoServiceProvider的本机文件格式(当您使用ExportCspBlob时)被称为PRIVATEKEYBLOB或PUBLICKEYBLOB(取决于是否包含私钥)。将Java IPrivateKey编码为PRIVATEKEYBLOB需要一些显然仅在最初生成的IPrivateKey实例上可用的字段(一个从存储中反序列化的字段不会转换为必要的IRSAPrivateCrtKey接口。)< / p>