使用 DPAPI 更新 XDocument 不起作用?
updating XDocument with DPAPI not working?
我是 C# 和密码学的新手,但我想保护一些数据,例如在 C# 项目中使用 DPAPI 的帐户。
我尝试了一些方法来做到这一点,但传递的数据是 XDocument 并且必须保持原样。
我尝试传递一个字符串并修改它没有问题,但是当涉及到 XML 数据时它被破坏了。
我正在使用 MS dotnet 标准的示例。
此代码有效(文件初始化)
byte[] toEncrypt = null;
byte[] entropy = CreateRandomEntropy();
FileStream fStream = new FileStream("Data.dat", FileMode.OpenOrCreate);
var length = new System.IO.FileInfo("Data.dat").Length;
if (length == 0)
{
XDocument doc =
new XDocument(
new XElement("data",
new XElement("global"),
new XElement("accounts")
)
);
toEncrypt = UnicodeEncoding.ASCII.GetBytes(doc.ToString());
EncryptDataToStream(toEncrypt, entropy, DataProtectionScope.CurrentUser, fStream);
}
fStream.Close();
然后我用一些数据更新了之前的示例:
fStream = new FileStream("Data.dat", FileMode.OpenOrCreate);
byte[] decryptData = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, 2);
string xml = UnicodeEncoding.ASCII.GetString(decryptData);
XDocument xmlData = XDocument.Parse(xml);
int maxId = 0;
if (xmlData.Descendants("account").Any())
{
maxId = xmlData.Descendants("account")
.Max(x => (int)x.Attribute("id"));
}
maxId++;
var compteElement = new XElement("account",
new XAttribute("id", maxId),
new XElement("login", "monemail@home.fr"),
new XElement("label", "compte TEST")
);
xmlData.Element("data").Element("accounts").Add(compteElement);
MemoryStream ms = new MemoryStream();
var settings = new XmlWriterSettings()
{
Indent = true
};
using (var writer = XmlWriter.Create(ms, settings))
{
xmlData.WriteTo(writer);
writer.Flush();
StreamReader sr = new StreamReader(ms);
ms.Seek(0, SeekOrigin.Begin);
String content = sr.ReadToEnd();
byte[] BytedxmlData = UnicodeEncoding.ASCII.GetBytes(content);
int bytesWritten = EncryptDataToStream(BytedxmlData, entropy, DataProtectionScope.CurrentUser, fStream);
}
fStream.Flush();
fStream.Close();
然后我尝试读取数据:
fStream = new FileStream("Data.dat", FileMode.Open);
byte[] decryptData2 = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, 2);
Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(decryptData2));
fStream.Close();
Data.dat 每次更新时添加的字节都会增长。有些我认为它被正确填充但是当我阅读它时,我只得到第一条记录初始化文件和任何更新。
加解密方法如下:
public static int EncryptDataToStream(byte[] Buffer, byte[] Entropy, DataProtectionScope Scope, Stream S)
{
if (Buffer == null)
throw new ArgumentNullException("Buffer");
if (Buffer.Length <= 0)
throw new ArgumentException("Buffer");
if (Entropy == null)
throw new ArgumentNullException("Entropy");
if (Entropy.Length <= 0)
throw new ArgumentException("Entropy");
if (S == null)
throw new ArgumentNullException("S");
int length = 0;
byte[] encryptedData = ProtectedData.Protect(Buffer, Entropy, Scope);
if (S.CanWrite && encryptedData != null)
{
S.Write(encryptedData, 0, encryptedData.Length);
length = encryptedData.Length;
}
return length;
}
public static byte[] DecryptDataFromStream(byte[] Entropy, DataProtectionScope Scope, Stream S, int Length)
{
if (S == null)
throw new ArgumentNullException("S");
if (Length <= 0)
throw new ArgumentException("Length");
if (Entropy == null)
throw new ArgumentNullException("Entropy");
if (Entropy.Length <= 0)
throw new ArgumentException("Entropy");
byte[] inBuffer = new byte[S.Length];
byte[] outBuffer;
if (S.CanRead)
{
S.Read(inBuffer, 0, inBuffer.Length);
outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope);
}
else
{
throw new IOException("Could not read the stream.");
}
return outBuffer;
}
感谢@jdweng 我来自编码。
必须将 UnicodeEncoding.ASCII 更改为 Encoding.UTF-8
我是 C# 和密码学的新手,但我想保护一些数据,例如在 C# 项目中使用 DPAPI 的帐户。 我尝试了一些方法来做到这一点,但传递的数据是 XDocument 并且必须保持原样。
我尝试传递一个字符串并修改它没有问题,但是当涉及到 XML 数据时它被破坏了。
我正在使用 MS dotnet 标准的示例。
此代码有效(文件初始化)
byte[] toEncrypt = null;
byte[] entropy = CreateRandomEntropy();
FileStream fStream = new FileStream("Data.dat", FileMode.OpenOrCreate);
var length = new System.IO.FileInfo("Data.dat").Length;
if (length == 0)
{
XDocument doc =
new XDocument(
new XElement("data",
new XElement("global"),
new XElement("accounts")
)
);
toEncrypt = UnicodeEncoding.ASCII.GetBytes(doc.ToString());
EncryptDataToStream(toEncrypt, entropy, DataProtectionScope.CurrentUser, fStream);
}
fStream.Close();
然后我用一些数据更新了之前的示例:
fStream = new FileStream("Data.dat", FileMode.OpenOrCreate);
byte[] decryptData = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, 2);
string xml = UnicodeEncoding.ASCII.GetString(decryptData);
XDocument xmlData = XDocument.Parse(xml);
int maxId = 0;
if (xmlData.Descendants("account").Any())
{
maxId = xmlData.Descendants("account")
.Max(x => (int)x.Attribute("id"));
}
maxId++;
var compteElement = new XElement("account",
new XAttribute("id", maxId),
new XElement("login", "monemail@home.fr"),
new XElement("label", "compte TEST")
);
xmlData.Element("data").Element("accounts").Add(compteElement);
MemoryStream ms = new MemoryStream();
var settings = new XmlWriterSettings()
{
Indent = true
};
using (var writer = XmlWriter.Create(ms, settings))
{
xmlData.WriteTo(writer);
writer.Flush();
StreamReader sr = new StreamReader(ms);
ms.Seek(0, SeekOrigin.Begin);
String content = sr.ReadToEnd();
byte[] BytedxmlData = UnicodeEncoding.ASCII.GetBytes(content);
int bytesWritten = EncryptDataToStream(BytedxmlData, entropy, DataProtectionScope.CurrentUser, fStream);
}
fStream.Flush();
fStream.Close();
然后我尝试读取数据:
fStream = new FileStream("Data.dat", FileMode.Open);
byte[] decryptData2 = DecryptDataFromStream(entropy, DataProtectionScope.CurrentUser, fStream, 2);
Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(decryptData2));
fStream.Close();
Data.dat 每次更新时添加的字节都会增长。有些我认为它被正确填充但是当我阅读它时,我只得到第一条记录初始化文件和任何更新。
加解密方法如下:
public static int EncryptDataToStream(byte[] Buffer, byte[] Entropy, DataProtectionScope Scope, Stream S)
{
if (Buffer == null)
throw new ArgumentNullException("Buffer");
if (Buffer.Length <= 0)
throw new ArgumentException("Buffer");
if (Entropy == null)
throw new ArgumentNullException("Entropy");
if (Entropy.Length <= 0)
throw new ArgumentException("Entropy");
if (S == null)
throw new ArgumentNullException("S");
int length = 0;
byte[] encryptedData = ProtectedData.Protect(Buffer, Entropy, Scope);
if (S.CanWrite && encryptedData != null)
{
S.Write(encryptedData, 0, encryptedData.Length);
length = encryptedData.Length;
}
return length;
}
public static byte[] DecryptDataFromStream(byte[] Entropy, DataProtectionScope Scope, Stream S, int Length)
{
if (S == null)
throw new ArgumentNullException("S");
if (Length <= 0)
throw new ArgumentException("Length");
if (Entropy == null)
throw new ArgumentNullException("Entropy");
if (Entropy.Length <= 0)
throw new ArgumentException("Entropy");
byte[] inBuffer = new byte[S.Length];
byte[] outBuffer;
if (S.CanRead)
{
S.Read(inBuffer, 0, inBuffer.Length);
outBuffer = ProtectedData.Unprotect(inBuffer, Entropy, Scope);
}
else
{
throw new IOException("Could not read the stream.");
}
return outBuffer;
}
感谢@jdweng 我来自编码。 必须将 UnicodeEncoding.ASCII 更改为 Encoding.UTF-8