C#加密XML文件

abm*_*bmv 8 c# encryption

我需要两个方法来加密,一个用密钥="hello world"来解密xml文件,密钥hello world应该用于加密和解密xml文件.这些方法应该适用于所有机器!任何加密方法都可以.XML文件内容如下:

<root>
    <lic>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </lic>
</root>
Run Code Online (Sandbox Code Playgroud)

有些人可以给我一个示例吗?问题是msdn示例encyptions使xml文件被加密但是当我在另一台机器上解密时它不起作用.例如

我尝试了这个示例: 如何:使用非对称密钥加密XML元素,但这里有一些有点会话,而在另一台机器上它说坏数据phewf!

Kob*_*obi 14

如果你想要加密和解密的相同密钥,你应该使用对称方法(这就是定义,真的).这是与您的样本最接近的一个(相同的来源). http://msdn.microsoft.com/en-us/library/sb7w85t6.aspx

发布的示例无效,因为它们没有使用相同的密钥.不仅在不同的机器上:在同一台机器上运行程序两次也不应该工作(对我来说不起作用),因为它们每次都使用不同的随机密钥.
尝试在创建密钥后添加此代码:

key = new RijndaelManaged();

string password = "Password1234"; //password here
byte[] saltBytes = Encoding.UTF8.GetBytes("Salt"); // salt here (another string)
var p = new Rfc2898DeriveBytes(password, saltBytes); //TODO: think about number of iterations (third parameter)
// sizes are devided by 8 because [ 1 byte = 8 bits ]
key.IV = p.GetBytes(key.BlockSize / 8);
key.Key = p.GetBytes(key.KeySize / 8);
Run Code Online (Sandbox Code Playgroud)

现在程序使用相同的密钥和初始向量,加密和解密应该适用于所有计算机.
另外,考虑重新命名keyalgorithm,否则这是非常误导的.我会说这是来自MSDN的一个糟糕的,不好用的例子.

注意:PasswordDeriveBytes.GetBytes()由于类中存在严重(安全)问题而被弃用PasswordDeriveBytes.上面的代码已被重写为使用更安全的Rfc2898DeriveBytes类(PBKDF2而不是PBKDF1).使用上述使用生成的代码PasswordDeriveBytes可能会受到影响.

另请参阅:使用PKBDF2-SHA256时推荐的迭代次数?

  • @Kobi Microsoft API(任何API)的问题在于它们的指定不足.最好使用`byte []密码,byte [] salt,int iterations`构造函数(编辑的答案中缺少迭代计数).问题是,使用API​​,无法知道密码的字符编码,盐.默认迭代计数也是如此.对于任何类型的互操作性(甚至可能在两个不同的.NET运行时之间),使用其他构造函数最多也是危险的. (2认同)

Vil*_*lx- 6

首先,如果你想使用相同的密钥进行加密和解密,你应该看看对称密码学。非对称加密是指加密和解密的密钥不同。只是为了让您知道 - RSA 是非对称的,TripleDES 和 Rijndael 是对称的。还有其他的,但 .NET 没有它们的默认实现。

我建议学习System.Security.Cryptography namespace. 并学习一些关于所有这些东西的知识。它拥有加密和解密文件以及生成密码所需的一切。特别是,您可能对这些类感兴趣:

  • CryptoStream
  • PasswordDeriveBytes
  • RijndaelManaged

在 MSDN 中也有使用示例。您可以使用这些类来加密任何文件,而不仅仅是 XML。但是,如果您只想加密选定的几个元素,则可以查看System.Security.Cryptography.Xml命名空间。我看到你已经找到了一篇关于它的文章。继续点击该页面上的链接,您将了解有关这些课程的更多信息。


sis*_*sve 5

如果您使用私钥对<lic>元素签名并将结果添加到文件(也许在<hash>元素中),效果会更好。如果您的支持人员需要知道许可证号或有效期,这将使每个人都可以读取xml文件,但是如果没有私钥,他们将无法更改任何值。

验证签名所需的公钥将是常识。

说明性
对代码进行签名只会保护代码免受更改,不会隐藏任何信息。您最初的问题是关于加密的,但是我不确定是隐藏数据还是只是保护数据不被修改是必需的。

示例代码:(从不发布PrivateKey.key。仅在对xml文件签名时才需要ServerMethods,仅在验证xml文件时才需要ClientMethods。)

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()); }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)