Signe de données avec MD5WithRSA.Pem/.Pkcs8 fichier-clé en C#

j'ai l'exemple de code suivant en Java, et j'ai besoin de revivre en C#:

PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(pkcs8PrivateKey);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
Signature sign = Signature.getInstance("MD5withRSA");

sign.initSign(privKey);
sign.update(data);
byte[] signature = sign.sign();

Est-ce possible avec L'API Crypto standard de .Net, ou devrais-je utiliser BouncyCastle? Merci,

b.

8
demandé sur rook 2010-02-16 20:19:56

5 réponses

je suis en train de rencontrer un problème très similaire en essayant de créer un outil natif C# pour empaqueter les extensions Chrome (en utilisant SHA1, pas MD5, mais ce n'est pas une grande différence). Je crois que j'ai essayé littéralement toutes les solutions possibles pour .Net: System.Sécurité.Cryptographie, BouncyCastle, OpenSSL.Net et Chilkat RSA.

La meilleure solution est probablement Chilkat; leur interface est la plus propre et la plus simple, elle est bien soutenue et bien documentée, et il y a un million exemple. Par exemple, voici un code utilisant leur bibliothèque qui fait quelque chose de très proche de ce que vous voulez: http://www.example-code.com/csharp/rsa_signPkcs8.asp. Cependant, ce n'est pas gratuit (bien que 150 $ne soit pas déraisonnable, vu que j'ai brûlé 2 jours à essayer de comprendre cela, et je fais un peu plus de 75 $par jour!).

comme alternative libre, JavaScience offre un certain nombre d'Utilités de crypto sous forme de source pour plusieurs langues (y compris C#/.Net) à http://www.jensign.com/JavaScience/cryptoutils/index.html. Celui qui est le plus saillant à ce que vous essayez de faire est opensslkey (http://www.jensign.com/opensslkey/index.html), qui vous permettra de générer un RSACryptoServiceProvider à partir d'un .fichier pem. Vous pouvez ensuite utiliser ce fournisseur pour signer votre code:

        string pemContents = new StreamReader("pkcs8privatekey.pem").ReadToEnd();
        var der = opensslkey.DecodePkcs8PrivateKey(pemContents);
        RSACryptoServiceProvider rsa = opensslkey.DecodePrivateKeyInfo(der);

        signature = rsa.SignData(data, new MD5CryptoServiceProvider());
3
répondu Tim Keating 2010-02-19 19:39:28

une autre façon est d'utiliser CNG (cryptographie de la prochaine génération), avec la sécurité.Cryptographie DLL de CodePlex

alors vous pouvez écrire:

byte[] dataToSign = Encoding.UTF8.GetBytes("Data to sign");
using (CngKey signingKey = CngKey.Import(pkcs8PrivateKey, CngKeyBlobFormat.Pkcs8PrivateBlob))
  using (RSACng rsa = new RSACng(signingKey))
  {
    rsa.SignatureHashAlgorithm = CngAlgorithm.MD5;
    return rsa.SignData(dataToSign);
  }

mise à Jour merci à Simon Mourier: avec .Net de 4,6, vous n'avez plus besoin d'une bibliothèque distincte

9
répondu Timores 2016-10-10 18:12:27

Ce DONC, la question répond à la partie PKCS#8 de votre code. Le reste des classes.net RSA sont un mélange bizarre de classes partiellement imbriquées qui sont très difficiles à comprendre. Il apparaît certainement que le support de signature est dans L'une ou l'autre des classes RSACryptoServiceProvider et/ou RSAPKCS1SignatureFormatter.

1
répondu James K Polk 2017-05-23 12:32:24

Avertissement: je connais Java et la cryptographie, mais ma connaissance de C# et .NET est très limitée. Je n'écris ici que sous l'influence de mes compétences en Google-fu.

en supposant que vous puissiez décoder une clé privée PKCS # 8-encodée RSA, alors, à partir de ce que j'ai lu sur MSDN, le reste du code devrait ressembler à ceci:

byte[] hv = MD5.Create().ComputeHash(data);
RSACryptoServiceProvider rsp = new RSACryptoServiceProvider();
RSAParameters rsp = new RSAParameters();
// here fill rsp fields by decoding pkcs8PrivateKey
rsp.ImportParameters(key);
RSAPKCS1SignatureFormatter rf = new RSAPKCS1SignatureFormatter(rsp);
rf.SetHashAlgorithm("MD5");
byte[] signature = rf.CreateSignature(hv);

les classes pertinentes sont dans le System.Security.Cryptography espace de noms.

comme pour le décodage PKCS#8 Blob Clé (c.-à-d. remplir le rsp champs), j'ai trouvé cette page qui décrit un utilitaire de ligne de commande en C# qui peuvent effectuer ce travail. Le code source est fourni et un seul fichier C#. D'après ce que j'y lis, ce code décode "manuellement" le fichier PKCS#8; indirectement, cela signifie que raw .NET (2.0) n'a pas de facilités pour le décodage de fichiers PKCS#8 (sinon l'auteur de cet outil ne se serait pas donné la peine de mettre en place un tel décodage). Pour votre tâche à portée de main, vous pouvez récupérer à partir de ce fichier source, les pièces dont vous avez besoin, sautant tout ce qui concerne le PEM et le cryptage symétrique; votre point d'entrée serait le DecodePrivateKeyInfo() fonction, qui s'attend apparemment à un fichier PKCS#8 non crypté DER-encoded, tout comme Java PKCS8EncodedKeySpec.

1
répondu Thomas Pornin 2010-02-19 19:38:13

Vous pouvez utiliser ce code . Au premier, vous devriez télécharger " BouncyCastle.Cryptographique.dll" de http://www.bouncycastle.org/csharp/