2009-03-19 7 views
1

La classe qui produit des erreurs « Bad Data »:System.Security.Cryptography et "Bad Data" - encodage de caractères?

 

using System; 
using System.Collections.Generic; 
using System.Security.Cryptography; 
using System.Text; 
using System.Windows.Forms; 

namespace MyNameSpace 
{ 

    public class RSAcrypt 
    { 
    private string _encryptedData; 
    private string _decryptedData; 

    public string EncryptedData 
    { 
     get { return _encryptedData; } 
     set { _encryptedData = value; } 
    } 

    public string DecryptedData 
    { 
     get { return _decryptedData; } 
     set { _decryptedData = value; } 
    } 

    public RSAcrypt() 
    { 
    } 
    /// <param name="CryptAction"> The action to perform on the string {Encrypt|Decrypt} </param > 
    /// <param name="StringToCrypt"> A string to perform the Action on </param> 
    public RSAcrypt(string CryptAction, string StringToCrypt) 
    { 
     UnicodeEncoding thisUnicodeEncoding = new UnicodeEncoding(); 
     RSACryptoServiceProvider thisRSACryptoServiceProvider = new RSACryptoServiceProvider(); 
     byte[] _stringToCrypt = thisUnicodeEncoding.GetBytes(StringToCrypt); 

     switch (CryptAction) 
     { 
      case "Encrypt": 
       byte[] encryptedData = Encrypt(_stringToCrypt, thisRSACryptoServiceProvider.ExportParameters(false)); 
       _encryptedData = thisUnicodeEncoding.GetString(encryptedData); 
      break; 

      case "Decrypt": 
       byte[] decryptedData = Decrypt(_stringToCrypt, thisRSACryptoServiceProvider.ExportParameters(true)); 
       _decryptedData = thisUnicodeEncoding.GetString(decryptedData); 
      break; 

      default: 

      break; 
     } 

    } 

    static private byte[] Encrypt(byte[] DataToEncrypt, RSAParameters keyInfo) 
    { 
     RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); 
     RSA.ImportParameters(keyInfo); 
     return RSA.Encrypt(DataToEncrypt, false); 
    } 

    static private byte[] Decrypt(byte[] DataToDecrypt, RSAParameters keyInfo) 
    { 
     #region Temporary Assignment - Remove before build 

     byte[] tmpVal = null; 

     #endregion 

     RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); 

     try 
     { 
      RSA.ImportParameters(keyInfo); 

      #region Temporary Assignment - Remove before build 

      tmpVal = RSA.Decrypt(DataToDecrypt, false); 

      #endregion 
     } 
     catch (Exception ex) 
     { 

      MessageBox.Show("Error: " + ex.Message, "Exception Thrown"); 

     } 

     #region Temporary Assignment - Remove before build 

     return tmpVal; 

     #endregion 
    } 
    } 
} 
 

Y at-il quelque chose que je peux changer dans cette classe qui me permettrait de vérifier l'encodage avant de passer le tableau d'octets à Crypter/Décrypter?

Il semble que j'ai une référence ici quelque part, mais je suis frustré de plus en, donc je pensais que ce serait au moins l'aide si je me suis arrêté pour faire autre chose que la lecture et la compilation ...

BTW , J'appelle cette classe pour écrire un mot de passe dans un fichier XML en utilisant le framework d'initialisation Nini. http://nini.sourceforge.net/manual.php#ASimpleExample

Aussi, je Notepad2 changer l'encodage du fichier (UTF-8) avant d'écrire dans le fichier XML.

C'était après que le programme s'est arrêté après que j'ai compilé la première fois. En utilisant le débogueur, j'ai pu voir que le codage était différent entre les données XML en mémoire (UTF-8) et les données sur disque (ANSI).

Cela ne semble pas être le cas maintenant, mais le programme s'arrête toujours, faisant référence aux mauvaises données renvoyées par la partie Decrypt de RSAcrypt(). (Notez également que Crypter et Décrypter étaient des méthodes identiques avant que ma frustration ne se mette en place, elles fonctionnent de la même manière, mais je voulais essayer de capturer des informations d'exception supplémentaires liées à la revendication de mauvaises données. J'ai laissé ma frustration handicaper mon code ;-))

Toutes les suggestions, idées ou références seraient grandes.

TIA,

E

+0

Si vous cryptez des données à stocker dans un fichier, utilisez AES. C'est plus performant, et c'est un chiffrement symétrique. – Alan

+0

RSA est mieux adapté si vous transmettez des données sensibles à une partie secondaire. – Alan

+0

Merci Alan, je prévoyais de passer à un autre chiffre une fois que l'application fonctionnera. Le système sera sur un sous-réseau privé avec un accès physique limité, mais je vais écrire des informations privées à la base de données, donc toutes les informations devront être cryptées. Merci encore, E – EtherealMonkey

Répondre

3

l'intérieur de votre constructeur vous générez une nouvelle paire de clés RSA chaque fois que vous faites:

RSACryptoServiceProvider thisRSACryptoServiceProvider = new RSACryptoServiceProvider(); 

Depuis votre constructeur est l'endroit où vous chiffrez et décryptez, vous cryptez avec une clé RSA, et décrypter avec une clé complètement différente. Pour que cela fonctionne, vous avez plusieurs options basées sur la façon dont vous prévoyez d'utiliser votre code.

Une option consiste à exporter la clé RSA et à l'utiliser pour toutes les opérations de chiffrement/déchiffrement. C'est la seule option si vous envisagez de décrypter/chiffrer les données entre les différentes exécutions de votre exécutable.

Bien sûr, cela glisse complètement sur comment vous allez stocker votre clé publique/privée (je recommande DPAPI sur Windows), pour une utilisation par votre application.

+0

Alan, Alors Encrypt et Decrypt méthodes font aussi un ImportParameters(), je pense que cela résout le problème «clés différentes». –

+0

À droite, cependant, la clé RSA transmise est régénérée chaque fois que vous appelez le constructeur RSAcrypt non défini par défaut. Étant donné que le constructeur est le seul moyen d'invoquer encrypt/decrypt, chaque fois que vous effectuez une opération de chiffrement/déchiffrement, vous obtenez une nouvelle paire de clés RSA. – Alan