The class that produces ‘Bad Data’ errors:
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 } } }
Is there anything that I can change in this class that would allow me to check the encoding prior to passing the byte array to Encrypt / Decrypt?
It seems like I have a reference around here somewhere, but I am becoming frustrated, so I thought it would at least help if I stopped to do something other than reading and compiling…
BTW, I am calling this class to write to a password to an XML file using the Nini initialization framework. http://nini.sourceforge.net/manual.php#ASimpleExample
Also, I used Notepad2 to change the file encoding (UTF-8) before I wrote to the XML file.
That was after the program halted after I compiled the first time. Using the debugger, I was able to see that the encoding was different between the XML data in memory (UTF-8) and the data on disk (ANSI).
That does not appear to be the case now, but the program still halts, referencing bad data returned from the Decrypt portion of RSAcrypt().
(also note that Encrypt and Decrypt were identical methods before my frustration set in, they do function the same, but I wanted to try to capture addition exception information related to the bad data claim. Of course, you will notice that I allowed my frustration to handicap my code 😉 )
Any suggestions, ideas or references would be great.
TIA,
E
Inside your constructor you generate a new RSA keypair each time when you do:
Since your constructor is where you encrypt and decrypt, you are encrypting with an RSA Key, and decrypting with a completely different one.
To make this work, you have several options based on how you plan to use your code.
One option is to export the RSA key, and use that for all encryption/decryption operations. This is the only option if you plan on decrypting/encrypting data between different runs of your executable.
Of course this completely glosses over how you will store your public/private key (I recommend DPAPI on windows), for use by your application.