Problème de cryptage / décryptage RSA in.NET

j'ai un problème avec le chiffrement C# et le déchiffrement en utilisant RSA. J'ai développé un service web qui sera envoyé des informations financières sensibles et les transactions. Ce que je voudrais pouvoir faire est du côté du client, crypter certains champs en utilisant la clé privée RSA du client, une fois qu'il a atteint mon service, il va décrypter avec la clé publique du client.

au moment où je continue à obtenir un "les données à déchiffrer dépassent le maximum pour ce module de 128 octets." exception. Je n'ai pas traité beaucoup avec la cryptographie C# RSA ainsi n'importe quelle aide serait grandement appréciée.

C'est la méthode que j'utilise pour générer les clés

private void buttonGenerate_Click(object sender, EventArgs e)
{
    string secretKey = RandomString(12, true);

    CspParameters param = new CspParameters();
    param.Flags = CspProviderFlags.UseMachineKeyStore;

    SecureString secureString = new SecureString();
    byte[] stringBytes = Encoding.ASCII.GetBytes(secretKey);
    for (int i = 0; i < stringBytes.Length; i++)
    {
        secureString.AppendChar((char)stringBytes[i]);
    }
    secureString.MakeReadOnly();
    param.KeyPassword = secureString;

    RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param);
    rsaProvider = (RSACryptoServiceProvider)RSACryptoServiceProvider.Create();
    rsaProvider.KeySize = 1024;


    string publicKey = rsaProvider.ToXmlString(false);
    string privateKey = rsaProvider.ToXmlString(true);

    Repository.RSA_XML_PRIVATE_KEY = privateKey;
    Repository.RSA_XML_PUBLIC_KEY = publicKey;

    textBoxRsaPrivate.Text = Repository.RSA_XML_PRIVATE_KEY;
    textBoxRsaPublic.Text = Repository.RSA_XML_PUBLIC_KEY;

    MessageBox.Show("Please note, when generating keys you must sign on to the gatewayn" +
        " to exhange keys otherwise transactions will fail", "Key Exchange", MessageBoxButtons.OK, MessageBoxIcon.Information);

}

une fois que j'ai généré les clés, j'envoie la clé publique au service web qui la stocke sous forme de fichier XML.

maintenant j'ai décidé de tester ceci donc voici ma méthode pour crypter une chaîne

public static string RsaEncrypt(string dataToEncrypt)
{
    string rsaPrivate = RSA_XML_PRIVATE_KEY;
    CspParameters csp = new CspParameters();
    csp.Flags = CspProviderFlags.UseMachineKeyStore;

    RSACryptoServiceProvider provider = new RSACryptoServiceProvider(csp);

    provider.FromXmlString(rsaPrivate);

    ASCIIEncoding enc = new ASCIIEncoding();
    int numOfChars = enc.GetByteCount(dataToEncrypt);
    byte[] tempArray = enc.GetBytes(dataToEncrypt);
    byte[] result = provider.Encrypt(tempArray, true);
    string resultString = Convert.ToBase64String(result);
    Console.WriteLine("Encrypted : " + resultString);
    return resultString;
}

j'obtiens ce qui semble être une valeur cryptée. Dans le test crypto web méthode que je créé, je prends ensuite ces données cryptées, essayer de décrypter les données en utilisant la clé publique des clients et de renvoyer cela dans le clair. Mais c'est là que l'exception est levée. Voici ma méthode pour responsable.

public string DecryptRSA(string data, string merchantId)
{
    string clearData = null;
    try
    {
        CspParameters param = new CspParameters();
        param.Flags = CspProviderFlags.UseMachineKeyStore;
        RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(param);

        string merchantRsaPublic = GetXmlRsaKey(merchantId);
        rsaProvider.FromXmlString(merchantRsaPublic);
        byte[] asciiString = Encoding.ASCII.GetBytes(data);

        byte[] decryptedData = rsaProvider.Decrypt(asciiString, false);

        clearData = Convert.ToString(decryptedData);
    }
    catch (CryptographicException ex)
    {
        Log.Error("A cryptographic error occured trying to decrypt a value for " + merchantId, ex);

    }
    return clearData;
}

Si quelqu'un pouvait m'aider ce serait génial, comme je l'ai dit je n'ai pas fait beaucoup avec C# RSA de chiffrement/déchiffrement.

17
demandé sur John Saunders 2010-03-19 11:28:11

5 réponses

Permettez-moi un peu de terminologie. Il n'y a de cryptage asymétrique et il y a signature numérique.

  • le cryptage asymétrique est une question de confidentialité. Certaines données sensibles est transformé en quelque chose d'illisible, sauf pour l'entité qui connaît la clé de déchiffrement. La clé de décryptage est nécessairement le privé clé: si la clé de déchiffrement est la clé publique, puis tout le monde peut déchiffrer les données (la clé publique is, well, public) et il n'y a plus de confidentialité. Dans le cryptage asymétrique, on crypte avec la clé publique et on décrypte avec la clé privée correspondante.

  • les signatures numériques sont destinées à prouver l'intégrité. Quelqu'un calcule une sorte de checksum à clé sur les données, de sorte que le lien entre le checksum et les données peut être vérifié plus tard. C'est une" signature " seulement parce que le pouvoir de calculer ce checksum exige la connaissance de quelque chose qui n'est pas public -- en clair, la signature utilise le privé clé. La vérification, cependant, devrait être réalisable par n'importe qui, et donc utiliser la clé publique.

une certaine confusion découle du fait que "l'algorithme" RSA est en fait une opération mathématique qui peut être déclinée à la fois dans un système de cryptage asymétrique et dans un système de signature numérique. La confusion est encore renforcée par la norme RSA, alias PKCS#1, qui s'appuie implicitement sur la façon dont les signatures numériques RSA ont été décrites pour la première fois, c'est-à-dire comme un "cryptage inversé" ("le signataire crypte les données avec sa clé privée"). Ce qui mène à des choses comme les signatures RSA appelées "sha1WithRSAEncryption". C'est tout à fait regrettable.

par conséquent, vous devez d'abord décider si vous voulez la confidentialité ou des signatures. Pour la confidentialité, pour les données envoyées clients le serveur, le serveur doit posséder une clé privée, et la les clients utilisent clé publique du serveur pour chiffrer les données. Pour les signatures, chaque client dispose de sa propre clé privée et de l'utiliser pour signer les données, et le serveur vérifie les signatures. De votre description, Je ne peux pas dire ce que vous recherchez vraiment, grâce à la confusion à laquelle je fais allusion ci-dessus.

il y a aussi quelque chose qui s'appelle authentification qui peut ressembler à des signatures numériques, mais il est plus faible. Le point de signatures est que personne peut vérifier la signature. En particulier, la signature peut être montrée à un juge et ainsi servir d'Arme légale contre le signataire (la signature est juridiquement contraignante -- du moins si vous la faites correctement, et dans l'état actuel de la réglementation sur les signatures électroniques, ce n'est pas facile). Dans la plupart des cas, vous avez seulement besoin de quelque chose de plus faible et plus simple, dans lequel le serveur est convaincu qu'il parle au bon client, mais ne peut pas ensuite convaincre quelqu'un d'autre que ce client était vraiment là. N'importe quel site Web avec des mots de passe d'utilisateur utilise une telle authentification.

cela étant dit...

  • le cryptage asymétrique RSA ne couvre que les messages courts. Pour une clé RSA de 1024 bits (c.-à-d. Une clé où la partie la plus importante, le "module RSA", est un grand nombre avec une valeur entre 2^1023 et 2^1024, et les messages chiffrés seront de longueur 128 octets), la taille maximale d'un message chiffré est de 117 octets (c'est la source réelle de votre erreur message.) Quand nous voulons envoyer des messages plus longs, nous utilisons un système hybride, dans lequel nous ne cryptons qu'un petit tas de bits aléatoires (disons 128 bits) et utilisons ce tas comme clé pour un chiffrement symétrique système (par exemple AES) qui peut traiter des messages beaucoup plus longs (et beaucoup plus rapides, aussi).

  • les signatures RSA, de même, ne peuvent être calculées que sur des messages courts, d'où la norme PKCS#1 qui prescrit qu'une signature est effectivement calculée sur une valeur de hachage. Hachage la valeur est le résultat d'un spécifique fonction de hachage, qui est calculé sur le message à signer. La fonction de hachage a une sortie de taille fixe (par exemple 256 bits pour SHA-256) mais accepte des messages d'entrée de (presque) longueur arbitraire. Les fonctions de hachage sont publiques (il n'y a pas de clé dedans) et, pour une sécurité appropriée, doivent avoir quelques propriétés spéciales. SHA-256 est, dès à présent, pas un mauvais choix. Il a été prouvé que le SHA-1 (un prédécesseur du SHA-256) présente certaines faiblesses et il convient de l'éviter. MD5 a (a sorte-d'oncle de SHA-1) A de plus grandes faiblesses et ne doit pas être utilisé.

  • L'utilisation correcte du cryptage asymétrique, en particulier dans un schéma hybride, et des signatures numériques, est plus délicate que ce que le texte ci-dessus peut suggérer. Il est tres facile de se tromper à un certain point, invisible, c'est-à-dire que le code semblera fonctionner mais laissera échapper des données utiles pour un attaquant. droit la façon d'utiliser le chiffrement asymétrique ou les signatures numériques repose sur protocoles existants, bien pensés. Un protocole est un ensemble d'éléments cryptographiques dans un système cohérent, où les fuites sont pris en charge. Le premier exemple est TLS, aussi connu sous le nom de SSL. Il s'agit d'un protocole qui assure la transmission de données confidentielles, avec intégrité et authentification (éventuellement authentification mutuelle). Le protocole HTTPS est un mélange de HTTP et de SSL. Le bon côté est que HTTPS a des implémentations existantes, notamment en C#. Le code le plus facile à implémenter et à déboguer est le code qui a déjà été implémenté et débogué. Utilisez donc HTTPS et vous vivrez plus longtemps et plus heureux.

33
répondu Thomas Pornin 2010-03-19 12:44:19

je comprends pourquoi vous posez la question. Le problème est que RSA n'est pas utilisé comme un code de bloc typique (comme AES ou 3DES) qui chiffre 8 octets à la fois, toute la journée. RSA est une opération mathématique qui renvoie le reste d'une division (modulo). De retour à l'école primaire, lorsque vous avez appris la division longue, rappelez-vous que le reste ne peut jamais être plus grand que le diviseur:si vous divisez 20 par 7, Votre reste est 6. Peu importe quel entier vous divisez par 7, le reste ne peut pas être supérieur à six.

RSA mathématiques est de la même façon. Par exemple, si vous utilisez une clé publique RSA de 1024 bits, le reste ne peut jamais être supérieur à 2^1024, soit seulement 128 octets. Donc, vous ne pouvez crypter 128 octets à la fois avec cette clé. (C'est une des raisons pour lesquelles nous mesurons la taille des clés RSA par le nombre de bits.)

techniquement, vous pouvez utiliser cette clé RSA dans une boucle pour chiffrer 128 octets de vos données à la fois. En réalité, nous ne le faisons presque jamais. parce que les maths RSA sont grandes et lentes. Au lieu de cela, nous utilisons ce qu'on appelle le cryptage "en deux phases". Nous utilisons RSA pour chiffrer seulement une courte "clé de session", puis utiliser cette clé de session dans un code de bloc à clé symétrique rapide (comme AES) pour chiffrer les données réelles.

le protocole entier est:

  1. obtenez la clé publique RSA de votre destination. Si c'est le cas, assurez-vous de valider le certificat pour vous assurer que la clé est authentique. Disons que la clé RSA fait 2048 bits de long.
  2. générer un nombre pseudo-aléatoire cryptographiquement fort à utiliser comme clé pour le bloc de chiffre (vous avez besoin de 256 bits comme clé pour AES-256, par exemple.) Notez que 256 < 2048, Le max que RSA-2048 peut chiffrer en une seule fois. Nous appelons ce nombre aléatoire la "clé de session".
  3. chiffrez la clé de session en utilisant la clé publique RSA 2048-bit. Il vous donnera 2048 bits de clé de session cryptée. Notez que cette opération est très lent.
  4. chiffrez toutes les données secrètes en utilisant AES-256, en utilisant la clé de session. Notez que c'est beaucoup plus rapide que l'étape 3.
  5. regrouper l'ID de la clé publique du certificat, la clé de session cryptée RSA, et les données cryptées AES ensemble. Je l'étiquetterais aussi avec un identificateur de format et un numéro de version, pour que vous sachiez dans quel format il est et comment le déchiffrer.
  6. envoyer le paquet à destination.

  7. à la destination vous utilisez l'Identificateur de format et la version pour démonter le paquet.

  8. récupérez la clé privée dont l'identité se trouve dans le champ ID de la clé publique.
  9. utilisez cette clé privée dans RSA pour décrypter la clé de session.
  10. utilisez la clé de session dans AES pour décrypter les données.

si vous allez faire cela, vous devez savoir que c'est exactement ce que le format CMS (PKCS#7) est pour. Je vous encourage à en apprendre davantage sur la norme et à l'adopter, plutôt que d'essayer d'inventer votre propre format. Le CSP de Microsoft le supporte, donc ça devrait être facile.

si vous ne suivez pas une norme, vous devrez prendre vos propres décisions au sujet de choses comme "Quel format les bits de la clé AES devraient-ils être dans le processus de cryptage RSA?"Plus probablement, vous feriez presque certainement des erreurs de sécurité, affaiblissant votre système. En outre, vous trouverez que des outils tels que le CSP sera très difficile à travailler avec si vous ne suivez pas une norme.

14
répondu John Deters 2010-03-26 04:42:23

en Déchifftrsa, la base de données 64 est-elle encodée? Si elle est, vous devez annuler cette première.

honnêtement, je pense que vous ne devriez pas mettre en œuvre cette routine vous-même pour protéger les "informations financières sensibles", sauf si vous avez beaucoup d'expérience avec la cryptographie. Il y a beaucoup de façons de faire des erreurs. Mieux utiliser une solution prête-peut-être SSL et les certificats, ou tout simplement PGP ou GnuPG?

3
répondu stmax 2010-03-19 08:47:29

RSA est principalement utilisé pour valider les hachures sécurisées de données - plutôt que de crypter les données elles-mêmes. Donc, un gros tas de données, vous pouvez utiliser SHA512 pour créer un hachage de données, puis utiliser RSA signe que de hachage.

vous voudrez utiliser un algorithme de cryptage symétrique pour de grands blocs de données - quelque chose comme AES ou 3DES.

gérer des transactions sécurisées n'est pas facile et devrait être laissé à ces gars qui passent toute la journée et la nuit penser à ce sujet. Si vous exposez le service comme sur le web, il suffit D'utiliser SSL qui crypte déjà et sécurise vos données.

3
répondu Paul Alexander 2010-03-19 08:48:30

déterminez D'abord ce contre quoi vous essayez de vous protéger. Si vous " chiffrez "quelque chose en utilisant la clé privée, n'importe qui peut" déchiffrer " avec la clé publique, puisque la clé publique est - bien - public.

si vous voulez réellement le signer, vous devriez (comme L'explique Paul Alexander) signer un hachage avec la clé privée qui peut ensuite être vérifiée sur le serveur.

chiffrer données utilisant RSA vous devez d'abord générer une clé symétrique aléatoire (F. x. AES), chiffrez la clé en utilisant un public chiffrez les données à l'aide de la clé symétrique. Vous pouvez ensuite transmettre la clé cryptée ainsi que les données cryptées au détenteur du privé clé, qui peut alors être d'abord déchiffrer la clé chiffrée avec la clé privée, puis déchiffrer les données avec la clé symétrique.

vous pouvez également envisager D'utiliser SSL, mais n'oubliez pas d'examiner attentivement l'authentification. Vous aurez probablement besoin d'une authentification client décider quels certificats faire confiance (vous ne devez pas simplement accepter aveuglément tout certificat émis par Verisign).

2
répondu Rasmus Faber 2010-03-19 11:13:44