MPD
MPD

Reputation: 23

C# desktop aplication throws a Cryptographic Exception in the run time

First of all, let me admit that I am very new to C#, specially on using Cryptography. I developed a C# application to manage my log on and password information. I read the info from a Winform and store in an XML. the XML is encrypted.

The program works just fine in the machine where I have the code. Works in debugger and also works when I use the exe (out side of visual studio).

Now when I take the exe (whole bin directory) to my home computer (has C# express 2010), it crashes while trying to read/write any information in the xml. This is the error I get in exception dialog:

See the end of this message for details on invoking 
just-in-time (JIT) debugging instead of this dialog box.

************** Exception Text **************
System.Security.Cryptography.CryptographicException: Bad Data.

   at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
   at System.Security.Cryptography.Utils._DecryptKey(SafeKeyHandle hPubKey, Byte[] key, Int32 dwFlags)
   at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
   at System.Security.Cryptography.RSAPKCS1KeyExchangeDeformatter.DecryptKeyExchange(Byte[] rgbIn)
   at System.Security.Cryptography.Xml.EncryptedXml.DecryptKey(Byte[] keyData, RSA rsa, Boolean useOAEP)
   at System.Security.Cryptography.Xml.EncryptedXml.GetDecryptionKey(EncryptedData encryptedData, String symmetricAlgorithmUri)
   at System.Security.Cryptography.Xml.EncryptedXml.DecryptDocument()
   at MyCal.Calendar.Decrypt(String Doc, RSA Alg, String KeyName) in C:\Users\mpaudel\Desktop\MyCal\MyCal\Form1.cs:line 191
   at MyCal.Calendar.btnSaveAdd_Click(Object sender, EventArgs e) in C:\Users\mpaudel\Desktop\MyCal\MyCal\Form1.cs:line 971
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ButtonBase.WndProc(Message& m)
   at System.Windows.Forms.Button.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Loaded Assemblies **************
mscorlib
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5448 (Win7SP1GDR.050727-5400)
    CodeBase: file:///C:/Windows/Microsoft.NET/Framework64/v2.0.50727/mscorlib.dll
----------------------------------------
MyCal
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0.0
    CodeBase: file:///C:/Users/remoteuser/Desktop/Release/MyCal.exe
----------------------------------------
System.Windows.Forms
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5446 (Win7SP1GDR.050727-5400)
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5453 (Win7SP1GDR.050727-5400)
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5420 (Win7SP1.050727-5400)
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Windows.Forms.Calendar
    Assembly Version: 1.0.4359.17528
    Win32 Version: 1.0.0.0
    CodeBase: file:///C:/Users/remoteuser/Desktop/Release/System.Windows.Forms.Calendar.DLL
----------------------------------------
RicherTextBox
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0.0
    CodeBase: file:///C:/Users/remoteuser/Desktop/Release/RicherTextBox.DLL
----------------------------------------
System.Xml
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5420 (Win7SP1.050727-5400)
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
System.Configuration
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5420 (Win7SP1.050727-5400)
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
33fead0k
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5453 (Win7SP1GDR.050727-5400)
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
Microsoft.mshtml
    Assembly Version: 7.0.3300.0
    Win32 Version: 7.0.3300.0
    CodeBase: file:///C:/Windows/assembly/GAC/Microsoft.mshtml/7.0.3300.0__b03f5f7f11d50a3a/Microsoft.mshtml.dll
----------------------------------------
System.Security
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.5420 (Win7SP1.050727-5400)
    CodeBase: file:///C:/Windows/assembly/GAC_MSIL/System.Security/2.0.0.0__b03f5f7f11d50a3a/System.Security.dll
----------------------------------------

************** JIT Debugging **************
To enable just-in-time (JIT) debugging, the .config file for this
application or computer (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.

For example:

<configuration>
    <system.windows.forms jitDebugging="true" />
</configuration>

When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the computer
rather than be handled by this dialog box.

Please help me get through this. Thanks a lot for looking into it. - MP

Update:-

Here is my code. Please excuse if the code is horrible :-) It is my learning project.

public partial class frmLogOn : Form
    {
        public frmLogOn()
        {
            InitializeComponent();
        }

        string LOGON_FILE_NAME = "logon.xml";//"logon.xml";

        private void btnEnterLogon_Click(object sender, EventArgs e)
        {

            CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams); 
            Decrypt(LOGON_FILE_NAME, rsaKey, "rsaKey");


            //Read Password from the xml file
            XmlDocument xmlDoc = new XmlDocument();

            if (File.Exists(LOGON_FILE_NAME))
            {
                XmlTextReader rdrXml = new XmlTextReader(LOGON_FILE_NAME);
                string existingpswd;
                do
                {
                       switch (rdrXml.NodeType)
                       {
                        case XmlNodeType.Text:
                        existingpswd = rdrXml.Value;
                        if (this.txtpswdLogon.Text == existingpswd)
                        {
                            this.DialogResult = DialogResult.OK;

                        }
                        else
                        {
                            MessageBox.Show("Password did not match", "Validate Entry", MessageBoxButtons.OK);
                            rdrXml.Close();
                            Encrypt(LOGON_FILE_NAME, "Pswrds", "EncryptedElement1", rsaKey, "rsaKey");
                            return;

                        }
                        break;
                       }


                } while (rdrXml.Read());
                rdrXml.Close();
                Encrypt(LOGON_FILE_NAME, "Pswrds", "EncryptedElement1", rsaKey, "rsaKey");
            }
        }

        private void chkChangepswdLogon_CheckedChanged(object sender, EventArgs e)
        {
            if (this.chkChangepswdLogon.Checked == true)
            {
                this.Height = 180;
                this.txtNewPswdLogon.Visible = true;
                this.txtOldPswdLogon.Visible = true;
                this.btnChangeLogOn.Visible = true;
                this.txtOldPswdLogon.Focus();
            }
            else if (this.chkChangepswdLogon.Checked == false)
            {
                this.Height = 105;
                this.txtNewPswdLogon.Visible = false;
                this.txtOldPswdLogon.Visible = false;
                this.btnChangeLogOn.Visible = false;
            }
        }

        private void frmLogOn_Load(object sender, EventArgs e)
        {

        }

        private void btnChangeLogOn_Click(object sender, EventArgs e)
        {
            CspParameters cspParams = new CspParameters();
            cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);


            Decrypt(LOGON_FILE_NAME, rsaKey, "rsaKey");
            XmlTextReader reader = new XmlTextReader(LOGON_FILE_NAME);
            XmlDocument doc = new XmlDocument();
            doc.Load(reader);
            reader.Close();
            XmlNode oldRecord;
            XmlElement root = doc.DocumentElement;
            try
            {
                oldRecord = root.SelectSingleNode("/Pswrds/pswd[password='" + this.txtOldPswdLogon.Text + "']");
                if (oldRecord == null)
                {
                    MessageBox.Show("Wrong existing password, not authorized to change");
                    this.txtNewPswdLogon.Text = "";
                    this.txtOldPswdLogon.Text = "";
                    this.txtpswdLogon.Text = "";
                    return;
                    Encrypt(LOGON_FILE_NAME, "Pswrds", "EncryptedElement1", rsaKey, "rsaKey");
                }
            }
            catch
            {
                MessageBox.Show("Wrong existing password, not authorized to change");
                return;
                Encrypt(LOGON_FILE_NAME, "Pswrds", "EncryptedElement1", rsaKey, "rsaKey");
            }
            string aa = oldRecord.Value;
            XmlElement newRecord = doc.CreateElement("pswd");

            newRecord.InnerXml = "<password>" + this.txtNewPswdLogon.Text + "</password>" ;

            root.ReplaceChild(newRecord, oldRecord);
            //save the output to a file 
            doc.Save(LOGON_FILE_NAME);
            MessageBox.Show("Password successfully changed.");
            this.txtNewPswdLogon.Text = "";
            this.txtOldPswdLogon.Text = "";
            this.txtpswdLogon.Text = "";
            this.chkChangepswdLogon.Checked = false;


            Encrypt(LOGON_FILE_NAME, "Pswrds", "EncryptedElement1", rsaKey, "rsaKey");
        }



        public static void Encrypt(string Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string KeyName)
        {
            // Create an XmlDocument object.
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load(Doc);

            // Check the arguments.
            if (Doc == null)
                throw new ArgumentNullException("Doc");
            if (ElementToEncrypt == null)
                throw new ArgumentNullException("ElementToEncrypt");
            if (EncryptionElementID == null)
                throw new ArgumentNullException("EncryptionElementID");
            if (Alg == null)
                throw new ArgumentNullException("Alg");
            if (KeyName == null)
                throw new ArgumentNullException("KeyName");

            ////////////////////////////////////////////////
            // Find the specified element in the XmlDocument
            // object and create a new XmlElemnt object.
            ////////////////////////////////////////////////
            XmlElement elementToEncrypt = xmlDoc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;

            // Throw an XmlException if the element was not found.
            if (elementToEncrypt == null)
            {
                throw new XmlException("The specified element was not found");

            }
            RijndaelManaged sessionKey = null;

            try
            {
                //////////////////////////////////////////////////
                // Create a new instance of the EncryptedXml class
                // and use it to encrypt the XmlElement with the
                // a new random symmetric key.
                //////////////////////////////////////////////////

                // Create a 256 bit Rijndael key.
                sessionKey = new RijndaelManaged();
                sessionKey.KeySize = 256;

                EncryptedXml eXml = new EncryptedXml();

                byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
                ////////////////////////////////////////////////
                // Construct an EncryptedData object and populate
                // it with the desired encryption information.
                ////////////////////////////////////////////////

                EncryptedData edElement = new EncryptedData();
                edElement.Type = EncryptedXml.XmlEncElementUrl;
                edElement.Id = EncryptionElementID;
                // Create an EncryptionMethod element so that the
                // receiver knows which algorithm to use for decryption.

                edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
                // Encrypt the session key and add it to an EncryptedKey element.
                EncryptedKey ek = new EncryptedKey();

                byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false);

                ek.CipherData = new CipherData(encryptedKey);

                ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);

                // Create a new DataReference element
                // for the KeyInfo element.  This optional
                // element specifies which EncryptedData
                // uses this key.  An XML document can have
                // multiple EncryptedData elements that use
                // different keys.
                DataReference dRef = new DataReference();

                // Specify the EncryptedData URI.
                dRef.Uri = "#" + EncryptionElementID;

                // Add the DataReference to the EncryptedKey.
                ek.AddReference(dRef);
                // Add the encrypted key to the
                // EncryptedData object.

                edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
                // Set the KeyInfo element to specify the
                // name of the RSA key.


                // Create a new KeyInfoName element.
                KeyInfoName kin = new KeyInfoName();

                // Specify a name for the key.
                kin.Value = KeyName;

                // Add the KeyInfoName element to the
                // EncryptedKey object.
                ek.KeyInfo.AddClause(kin);
                // Add the encrypted element data to the
                // EncryptedData object.
                edElement.CipherData.CipherValue = encryptedElement;
                ////////////////////////////////////////////////////
                // Replace the element from the original XmlDocument
                // object with the EncryptedData element.
                ////////////////////////////////////////////////////
                EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
                xmlDoc.Save(Doc);
            }
            catch (Exception e)
            {
                // re-throw the exception.
                throw e;
            }
            finally
            {
                if (sessionKey != null)
                {
                    sessionKey.Clear();
                }

            }

        }

        public static void Decrypt(string Doc, RSA Alg, string KeyName)
        {
            // Create an XmlDocument object.
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load(Doc);
            // Check the arguments.  
            if (Doc == null)
                throw new ArgumentNullException("Doc");
            if (Alg == null)
                throw new ArgumentNullException("Alg");
            if (KeyName == null)
                throw new ArgumentNullException("KeyName");

            // Create a new EncryptedXml object.
            EncryptedXml exml = new EncryptedXml(xmlDoc);

            // Add a key-name mapping.
            // This method can only decrypt documents
            // that present the specified key name.
            exml.AddKeyNameMapping(KeyName, Alg);

            // Decrypt the element.
            exml.DecryptDocument();
            xmlDoc.Save(Doc);

        }





    }

Upvotes: 1

Views: 3159

Answers (2)

MPD
MPD

Reputation: 23

I finally found that both the machines I was trying to run the application did not have X.509 certificates installed because of which the code would throw exception while trying to decrypt. I Installed the certificate from this link [microsoft.com/en-us/download/details.aspx?id=14089], recompiled the application and now it works like a charm!! Thanks everyone for all your help!

Upvotes: 0

Dour High Arch
Dour High Arch

Reputation: 21712

These are comments, but the comment box is not large enough to contain them. This code:

catch (Exception e)
{
    // re-throw the exception.
    throw e;
}

is discarding your stack trace so you can't see what causes errors. Remove that code.

I suspect the Doc you are passing to Decrypt is not valid. Set a breakpoint before you call xmlDoc.Load(Doc) and inspect it. You'll have to show us what you are passing for Doc, or at least where MyCal.Calendar.btnSaveAdd_Click is getting it.

Also, you are calling

if (Doc == null)
    throw new ArgumentNullException("Doc");

after using Doc in xmlDoc.Load(Doc). That's too late, you must validate arguments before using them, not after.

Upvotes: 1

Related Questions