views:

55

answers:

1

Hi,

I have written some code that has encrypted an XML config file containing user credentials, and also the code to decrypt that file. When I run the encryption and decryption together on my local machine it works as expected. However, when I deploy the program, with only the decrypt code, the xml file will not decrypt. I get a cryptographic Exception: Bad Data? Here is my code:

    public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string Keyname)
    {
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (ElementToEncrypt == null)
            throw new ArgumentNullException("Element to Encrypt");
        if (EncryptionElementID == null)
            throw new ArgumentNullException("EncryptionElementID");
        if (Alg == null)
            throw new ArgumentNullException("ALG");
        //specify which xml elements to encrypt
        XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;

        if (elementToEncrypt == null)
            throw new XmlException("The specified element was not found");
        try
        {
            //create session key
            RijndaelManaged sessionkey = new RijndaelManaged();
            sessionkey.KeySize = 256;

            //encrypt using Encrypted exml object and hold in byte array
            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;

            edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
            //encrypt the session key and add it encrypted key 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 data reference to encrypted key

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

            edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));

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



        // 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);
    }


        catch (Exception e)
        {
            throw e;
        }
    }


    public static string Decrypt()
    {
            //create XML documentobject and load config file
            XmlDocument xmlDoc = new XmlDocument();

            try
            {
                xmlDoc.Load("config.xml");
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
            }

            //create container for key
            CspParameters cspParam = new CspParameters();
            cspParam.KeyContainerName = "XML_RSA_FTP_KEY";
            cspParam.Flags = CspProviderFlags.UseMachineKeyStore;
            //create key and store in container
            RSACryptoServiceProvider ftpkey = new RSACryptoServiceProvider(cspParam);


            //add keyname mapping qnd decrypt the document
            EncryptedXml exml = new EncryptedXml(xmlDoc);
            exml.AddKeyNameMapping("ftpkey", ftpkey);
            exml.DecryptDocument();

            //pass decrypted document to extract credentials method
            string details =  Extract_Credentials(xmlDoc);

            //return decrypted log in details
            return details;

    }

Any help would be appreciated. Thanks, Darren

A: 

The obvious question is how you moved the XML_RSA_FTP_KEY private key to the server.

If you did not do anything, the decrypt()-method will have generated a new keypair in the XML_RSA_FTP_KEY-container. This key will fail to decrypt the data which was encrypted with a different key and give the "Bad data"-exception.

Rasmus Faber
Thanks for the response. I haven't done anything with the private key other than what is within my code. This is the first time I have used encryption/decryption and I am struggling with this final part. I would appreciate it if you could point me in the right direction of what needs doing? Basically the XMl file and decrypt code will be bundled as part of a larger system to 7 different remote sites. Each site shoul dbe able to decrypt the file using the code. How would I get the private key to them? Thanks again.
darren young
You are now facing the same problem as every other software company in the world. This is the dilemma where DRM came out :P I am really interested to see what answer comes out of this though.
Adkins
One way to double check it to create a test harness such as a windows form with a text box and decrypt/encrypt button, this will allow you to test remotely the encryptions on the server in an easy to test way... Not much help but could point you in the right direction.
Xander