C#加密XML文件
我需要两种方法,一种是加密,另一种是用key=“hello world”解密xml文件,密钥hello world应该用来加密和解密xml文件。这些方法应该可以在所有机器上使用!!!任何加密方法都可以。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>
<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()); }
}
}
}