tags:

views:

2573

answers:

4

I need two methods one to encrypt and one to decrypt an xml file with a key= "hello world",the key hello world should be used to encrypt and decrypt the xml file.These methods should work on all machines!!! Any encryption methods will do. XML File contents below:

<root>
    <lic>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </lic>
</root>

Can some give me a sample?The issue is the msdn sample encyptions make a xml file encypted but when I decrypt on another machine it doesn't work.For example

I tried this sample: How to: Encrypt XML Elements with Asymmetric Keys, but here there is some kinda session and on another machine it says bad data phewf!

+4  A: 

If you want the same key for encrypting and decrypting you should use a symmetric method (that's the definition, really). Here's the closest one to your sample (same source). http://msdn.microsoft.com/en-us/library/sb7w85t6.aspx

The posted sample isn't working because they aren't using the same keys. Not only on different machines: running the program on the same machine twice should not work either (didn't work for me), because they use different random keys every time.
try adding this code after creating your key:

key = new RijndaelManaged();

byte[] passwordBytes = Encoding.UTF8.GetBytes("Password1234"); //password here
byte[] saltBytes = Encoding.UTF8.GetBytes("Salt"); // salt here (another string)
PasswordDeriveBytes p = new PasswordDeriveBytes(passwordBytes, saltBytes);
// sizes are devided by 8 because [ 1 byte = 8 bits ]
key.IV = p.GetBytes(key.BlockSize / 8);
key.Key = p.GetBytes(key.KeySize / 8);

Now the program is using the same key and initial vector, and Encrypt and Decrypt should work on all machines.
Also, consider renaming key to algorithm, otherwise this is very misleading. I'd say it's a bad, not-working-well example from MSDN.

Kobi
I tried that sample,If I comment out only decrypt,then encrypt and then comment out encrypt and the decrypt is does not work? Why?
abmv
Thanks,damn those msdn guys,well you saved my day.Thanks again for you time and resource.
abmv
abmv - Tsk, tsk, tsk - sounds like you just want a solution without understanding what it does!
Vilx-
Like I got time to understand all these complex encryption stuff.I was in-fact trying to understand by reading MSDN but if they cant explain it properly then who else can.You dont need to understand the whole Cryptographic Theory to encypt a file.Well .net has classes and I just need to use them to save my time!.And I they give you a example then atleast it should work on different machines!
abmv
If you are interested, on your free time, MSDN is not a good place to learn theory. I'd start with Wikipedia - http://en.wikipedia.org/wiki/Symmetric-key_algorithm . If you are very interested and want something in friendly English, The Code Book by Simon Singh is probably your best bet.
Kobi
I second Kobi's proposal for *The code Book*. It is highly entertaining and informative at the same time!
Treb
Any reason I'm getting down votes for this? Feel free to tell me if I've done something wrong.
Kobi
+2  A: 

Would be cooler if you used a private key to sign the <lic> element and added the result to the file (in a <hash> element perhaps). This would make it possibly for everyone to read the xml file in case your support needs to know the license number, or the date of expiry, but they can not change any values without the private key.

The public key needed to verify the signature would be common knowledge.

Clarification
Signing your code will only protect it against changes, it will not keep any information in it hidden. Your original question mentions encryption, but I am not sure that it is a requirement to hide the data, or just protect it from modification.

Example code: (Never publish PrivateKey.key. ServerMethods are only needed when signing the xml file, ClientMethods are only needed when verifying the xml file.)

using System;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

public static class Program {
    public static void Main() {
        if (!File.Exists("PublicKey.key")) {
            // Assume first run, generate keys and sign document.
            ServerMethods.GenerateKeyPair();

            var input = new XmlDocument();
            input.Load("input.xml");
            Debug.Assert(input.DocumentElement != null);

            var licNode = input.DocumentElement["lic"];
            Debug.Assert(licNode != null);

            var licNodeXml = licNode.OuterXml;
            var signedNode = input.CreateElement("signature");
            signedNode.InnerText = ServerMethods.CalculateSignature(licNodeXml);
            input.DocumentElement.AppendChild(signedNode);

            input.Save("output.xml");
        }

        if (ClientMethods.IsValidLicense("output.xml")) {
            Console.WriteLine("VALID");
        } else {
            Console.WriteLine("INVALID");
        }
    }

    public static class ServerMethods {
        public static void GenerateKeyPair() {
            var rsa = SharedInformation.CryptoProvider;

            using (var keyWriter = File.CreateText("PublicKey.key"))
                keyWriter.Write(rsa.ToXmlString(false));

            using (var keyWriter = File.CreateText("PrivateKey.key"))
                keyWriter.Write(rsa.ToXmlString(true));
        }

        public static string CalculateSignature(string data) {
            var rsa = SharedInformation.CryptoProvider;
            rsa.FromXmlString(File.ReadAllText("PrivateKey.key"));

            var dataBytes = Encoding.UTF8.GetBytes(data);
            var signatureBytes = rsa.SignData(dataBytes, SharedInformation.HashAlgorithm);
            return Convert.ToBase64String(signatureBytes);
        }
    }

    public static class ClientMethods {
        public static bool IsValid(string data, string signature) {
            var rsa = SharedInformation.CryptoProvider;
            rsa.FromXmlString(File.ReadAllText("PublicKey.key"));

            var dataBytes = Encoding.UTF8.GetBytes(data);
            var signatureBytes = Convert.FromBase64String(signature);
            return rsa.VerifyData(dataBytes, SharedInformation.HashAlgorithm, signatureBytes);
        }

        public static bool IsValidLicense(string filename) {
            var doc = new XmlDocument();
            doc.Load(filename);

            var licNode = doc.SelectSingleNode("/root/lic") as XmlElement;
            var signatureNode = doc.SelectSingleNode("/root/signature") as XmlElement;
            if (licNode == null || signatureNode == null) return false;

            return IsValid(licNode.OuterXml, signatureNode.InnerText);
        }
    }

    public static class SharedInformation {
        public static int KeySize {
            get { return 1024; }
        }

        public static string HashAlgorithm {
            get { return "SHA512"; }
        }

        public static RSACryptoServiceProvider CryptoProvider {
            get { return new RSACryptoServiceProvider(KeySize, new CspParameters()); }
        }
    }
}
Simon Svensson
I tried two sample from msdn but..the issue is I can get it to decypt properly on a diff machine.
abmv
+1  A: 

First of all, if you want to use the same key for encrypting and decrypting, you should look at symmetric cryptography. Asymmetric cryptography is when the keys for encrypting and decrypting are different. Just so that you know - RSA is asymmetric, TripleDES and Rijndael are symmetric. There are others too, but .NET does not have default implementations for them.

I'd advise studying the System.Security.Cryptography namespace. And learning a bit about all that stuff. It has all you need to encrypt and decrypt files, as well as generate a password. In particular, you might be interested in these classes:

  • CryptoStream
  • PasswordDeriveBytes
  • RijndaelManaged

There are also examples for usage in MSDN for each of them. You can use these classes to encrypt any file, not just XML. If however you want to encrypt just a select few elements, you can take a look at System.Security.Cryptography.Xml namespace. I see you've already found one article about it. Keep following the links on that page and you will learn more about those classes.

Vilx-
A: 

this is how you digitally sign and verify XML documents Sign XML Documents

Eros
also see one of the similar questions I raised here http://stackoverflow.com/questions/1031856/digitally-sign-parts-of-a-xml-document
Eros