RSA a lu la clé publique

J’ai une clé publique générée en utilisant Java avec l’algorithme RSA et capable de reconstruire en utilisant le code suivant:

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

QUESTION Comment construire PublicKey du côté dotnet en utilisant csharp?

Exemple de clé publique :, Dans le code ci-dessus, je transmet les données contenues dans l’élément codé.

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

Malheureusement, C # ne fournit aucun moyen simple de le faire. Mais cela décodera correctement une clé publique x509 (assurez-vous d’abord décoder le paramètre x509key en 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 ssortingng? { 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) //ssortingp 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; } 

Le code ci-dessus est basé sur cette question (qui ne fonctionnait que pour certaines tailles de clé). Le code ci-dessus fonctionnera pour pratiquement toutes les tailles de clé RSA. Il a été testé avec la clé fournie, ainsi que pour les clés 2048 bits et 4096 bits.

Une autre solution consisterait à générer un certificate à l’aide d’un outil ( XCA en est un bon), à exporter le certificate dans un fichier p12 (PKCS12), puis à charger le certificate à la fois en Java et en C # pour obtenir les clés.

En C #, vous pouvez charger un fichier PKCS12 à l’aide de la classe X509Certificate2 .

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

En Java, vous pouvez charger un fichier PKCS12 à l’aide de la classe KeyStore .

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

En Java, publicKey de PublicKey en RSAPublicKey .

Cela a getModulus et getExponent vous obtiendrez BigIntegers , à partir duquel vous utilisez toByteArray pour obtenir les octets.

Je ne sais pas si Java continue à être en tête de 0 dans la classe BigInteger , vérifiez donc si vous devez BigInteger les BigInteger nuls (0x00) de l’exposant public.

Encodez les tableaux d’octets en base 64 à l’aide du codec Apache Commons ou de l’encodeur Base64 de Java 8 .

Vous devrez peut-être vérifier l’ordre des octets (peut-être inverser le module, pas sûr).

Sérialisez-les en construisant ce XML: " {votre module public codé en base 64 ici} {votre exposant public codé en base 64 ici} " .

En CSharp:

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

Vous avez maintenant un CSP RSA chargé avec votre clé publique.

Le même processus peut être étendu pour charger une clé privée en ajoutant des éléments XML P, Q, DP, DQ et InverseQ.