Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#加密XML文件_C#_Encryption - Fatal编程技术网

C#加密XML文件

C#加密XML文件,c#,encryption,C#,Encryption,我需要两种方法,一种是加密,另一种是用key=“hello world”解密xml文件,密钥hello world应该用来加密和解密xml文件。这些方法应该可以在所有机器上使用!!!任何加密方法都可以。XML文件内容如下: <root> <lic> <number>19834209</number> <expiry>02/02/2002</expiry> </lic>

我需要两种方法,一种是加密,另一种是用key=“hello world”解密xml文件,密钥hello world应该用来加密和解密xml文件。这些方法应该可以在所有机器上使用!!!任何加密方法都可以。XML文件内容如下:

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

19834209
02/02/2002
有人能给我一个示例吗?问题是msdn示例百科使xml文件成为百科,但当我在另一台机器上解密时,它就不起作用了

我试过这个例子: ,
但这里有一个会话,在另一台机器上,它显示坏数据phewf

如果您想要相同的密钥进行加密和解密,则应使用对称方法(实际上,这就是定义)。这是最接近你的样本(同一来源)。

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

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);
现在,程序使用相同的密钥和初始向量,加密和解密应该可以在所有机器上运行。
此外,考虑重命名<代码>键<代码> > <代码>算法>代码>,否则这是非常误导的。我认为这是MSDN中的一个不好的例子

注意
PasswordDeriveBytes.GetBytes()
已被弃用,因为类中存在严重的(安全)问题。上面的代码已重写为使用更安全的
Rfc2898DeriveBytes
类(PBKDF2而不是PBKDF1)。使用上面的PasswordDeriveBytes生成的代码可能会被泄露。


另请参见:

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

验证签名所需的公钥是众所周知的

澄清
对代码进行签名只会保护代码不受更改的影响,不会隐藏其中的任何信息。您最初的问题提到了加密,但我不确定是否需要隐藏数据,或者只是保护数据不被修改

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


首先,如果您想使用相同的密钥进行加密和解密,您应该查看对称加密。非对称加密是指加密和解密的密钥不同。正如您所知,RSA是不对称的,TripleDES和Rijndael是对称的。还有其他的,但是.NET没有默认的实现

我建议研究
System.Security.Cryptography命名空间
。学习一下这些东西。它具有加密和解密文件以及生成密码所需的全部功能。特别是,您可能对这些类感兴趣:

  • 加密流
  • PasswordDeriveBytes
  • RijndaelManaged

在MSDN中也有针对每一个的使用示例。您可以使用这些类来加密任何文件,而不仅仅是XML。但是,如果您只想加密一小部分元素,可以查看
System.Security.Cryptography.Xml
namespace。我看你已经找到一篇关于它的文章了。继续关注该页面上的链接,您将了解有关这些类的更多信息。

这是您对XML文档进行数字签名和验证的方式。

我尝试了来自msdn的两个示例,但..问题是我可以在不同的机器上正确解密。我尝试了该示例,如果我只注释了解密,然后加密,然后注释掉加密和解密是不工作的?为什么?就像我有时间了解所有这些复杂的加密内容一样。事实上,我试图通过阅读MSDN来理解这些内容,但是如果他们不能正确地解释,那么还有谁能理解呢。你不需要了解整个加密理论来加密一个文件。好吧,.net有类,我只需要使用它们来节省我的时间!。我想他们给了你一个例子,然后至少它应该在不同的机器上工作!如果你有兴趣,在空闲时间,MSDN不是学习理论的好地方。我从维基百科开始。如果你非常感兴趣并且想要一些友好的英语,西蒙·辛格的代码书可能是你最好的选择。@Ofir-谢谢。我对代码进行了编辑,以使其能够编译(它是由其他人编辑的,他们破坏了它,或者可能是API更改了)。我不知道什么是
Rfc2898DeriveBytes
的最佳参数,但我添加了一个链接来回答这个问题(不幸的是,不是数字)。默认值为1000。@Kobi Microsoft API(任何API)的问题是它们的指定不足。最好使用
byte[]密码,byte[]salt,int iterations
构造函数(编辑的答案中缺少迭代计数)。问题是,使用API不可能知道密码salt的字符编码。默认迭代计数也是如此。对于任何类型的互操作性(甚至可能在两个不同的.NET运行时之间),使用其他构造函数充其量都是危险的。请发布一个简短的代码示例,并说明哪些代码不起作用(例如,“在第12行,我得到了一个编译器错误12345”,或“在运行时,我在第15行得到了一个SecurityException”).bad data thown by encyption class啊好的,你需要加密数据以隐藏它,还是仅仅保护数据不受更改?我需要加密整个文件,这样人们就不会篡改它。防止人们篡改它将符合
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()); }
        }
    }
}