RSA读取PublicKey

我有使用带算法RSA的 java生成的公钥,并能够使用以下代码重建:

X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(arrBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); publicKey = keyFactory.generatePublic(pubKeySpec); 

问题如何使用csharp在dotnet端构建PublicKey?

示例公钥将是:,在上面的代码中,我传递元素编码中包含的数据

   PUBLIC RSA X.509 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMf54mcK3EYJn9tT9BhRoTX+8AkqojIyeSfog9ncYEye 0VXyBULGg2lAQsDRt8lZsvPioORZW7eB6IKawshoWUsCAwEAAQ==  

不幸的是,C#没有提供任何简单的方法来做到这一点。 但这将正确解码x509公钥(确保首先对x509key参数进行Base64解码):

 public static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509key) { byte[] SeqOID = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; MemoryStream ms = new MemoryStream(x509key); BinaryReader reader = new BinaryReader(ms); if (reader.ReadByte() == 0x30) ReadASNLength(reader); //skip the size else return null; int identifierSize = 0; //total length of Object Identifier section if (reader.ReadByte() == 0x30) identifierSize = ReadASNLength(reader); else return null; if (reader.ReadByte() == 0x06) //is the next element an object identifier? { int oidLength = ReadASNLength(reader); byte[] oidBytes = new byte[oidLength]; reader.Read(oidBytes, 0, oidBytes.Length); if (oidBytes.SequenceEqual(SeqOID) == false) //is the object identifier rsaEncryption PKCS#1? return null; int remainingBytes = identifierSize - 2 - oidBytes.Length; reader.ReadBytes(remainingBytes); } if (reader.ReadByte() == 0x03) //is the next element a bit string? { ReadASNLength(reader); //skip the size reader.ReadByte(); //skip unused bits indicator if (reader.ReadByte() == 0x30) { ReadASNLength(reader); //skip the size if (reader.ReadByte() == 0x02) //is it an integer? { int modulusSize = ReadASNLength(reader); byte[] modulus = new byte[modulusSize]; reader.Read(modulus, 0, modulus.Length); if (modulus[0] == 0x00) //strip off the first byte if it's 0 { byte[] tempModulus = new byte[modulus.Length - 1]; Array.Copy(modulus, 1, tempModulus, 0, modulus.Length - 1); modulus = tempModulus; } if (reader.ReadByte() == 0x02) //is it an integer? { int exponentSize = ReadASNLength(reader); byte[] exponent = new byte[exponentSize]; reader.Read(exponent, 0, exponent.Length); RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSAParameters RSAKeyInfo = new RSAParameters(); RSAKeyInfo.Modulus = modulus; RSAKeyInfo.Exponent = exponent; RSA.ImportParameters(RSAKeyInfo); return RSA; } } } } return null; } public static int ReadASNLength(BinaryReader reader) { //Note: this method only reads lengths up to 4 bytes long as //this is satisfactory for the majority of situations. int length = reader.ReadByte(); if ((length & 0x00000080) == 0x00000080) //is the length greater than 1 byte { int count = length & 0x0000000f; byte[] lengthBytes = new byte[4]; reader.Read(lengthBytes, 4 - count, count); Array.Reverse(lengthBytes); // length = BitConverter.ToInt32(lengthBytes, 0); } return length; } 

上面的代码基于这个问题 (仅适用于某些密钥大小)。 上面的代码几乎适用于任何RSA密钥大小,并且已经使用您提供的密钥以及2048位和4096位密钥进行了测试。

另一种解决方案是使用工具生成证书( XCA是一个好的),将证书导出到p12(PKCS12)文件,然后在Java和C#中加载证书以获取密钥。

在C#中,您可以使用X509Certificate2类加载PKCS12文件。

 X509Certificate2 cert = new X509Certificate2(certificateFile, certificatePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); RSACryptoServiceProvider provider1 = (RSACryptoServiceProvider)cert.PublicKey.Key; RSACryptoServiceProvider provider2 = (RSACryptoServiceProvider)cert.PrivateKey; 

在Java中,您可以使用KeyStore类加载PKCS12文件。

 KeyStore keystore = KeyStore.getInstance("PKCS12"); keystore.load(new FileInputStream(certificateFile), certificatePassword.toCharArray()); Key key = keystore.getKey(certName, certificatePassword.toCharArray()); Certificate cert = keystore.getCertificate(certName); PublicKey publicKey = cert.getPublicKey(); KeyPair keys = new KeyPair(publicKey, (PrivateKey) key); 

在Java中,将PublicKeyPublicKey publicKeypublicKey

这有getModulusgetExponent将获得BigIntegers ,您可以使用toByteArray来获取字节。

我不知道Java在BigInteger类中保持领先0,因此检查是否必须从公共指数中去除前导空(0x00)字节。

使用Apache Commons Codec或Java 8的Base64 Encoder将字节数组编码到base 64中。

您可能需要检查字节顺序(可能反转模数,不确定)。

通过构造这个XML来序列化这些: " {your base 64 encoded public modulus here} {your base 64 encoded public exponent here} "

在CSharp中:

 var rsaCsp = new RSACryptoServiceProvider(o.BitLength); rsaCsp.FromXmlString(xmlRsaKeyValue); 

现在您已经加载了公钥的RSA CSP。

通过添加P,Q,DP,DQ和InverseQ XML元素,可以扩展相同的过程以加载私钥。