簡體   English   中英

使用 IXmlSerializable (c#) 時加密的 XML 文件

[英]Encrypted XML file when using IXmlSerializable (c#)

如何以加密方式編寫使用 IXmlSerializable 序列化的 XML 文件?

我將我的數據(包含節點的節點結構,就像文件系統文件夾一樣)(反)序列化為 xml 文件:

public class DataNodeCollection : List<DataNode>, IXmlSerializable
{
    internal void Serialize()
    {
        string sFilename = getFilename();
        using (var writer = new StreamWriter(sFilename, false, Encoding.Unicode))
        {
            var serializer = new XmlSerializer(this.GetType(), new XmlRootAttribute("SystemNodes"));
            serializer.Serialize(writer, this);
            writer.Flush();
        }
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteAttributeString("FileFormatVersion", CurrentFormatVersion.ToString(CultureInfo.InvariantCulture));

        foreach (DataNode elem in this)
        {
            var innerSerializer = new XmlSerializer(typeof(DataNode), new XmlRootAttribute(elem.Name));
            innerSerializer.Serialize(writer, elem);
        }
    }
}

public class DataNode : IXmlSerializable
{
        private IDictionary<string, string> _mapAttributes = new Dictionary<string, string>();
        private IList<DataNode> _subNodes = new List<DataNode>();

        public string Name { get; protected set; }

        public void WriteXmlXmlWriter writer)
        {
            foreach (string sKey in _mapAttributes.Keys)
            {
                writer.WriteAttributeString(sKey, _mapAttributes[sKey]);
            }

            foreach (DataNode node in _subNodes)
            {
                var innerSerializer = new XmlSerializer(typeof(DataNode), new XmlRootAttribute(node.Name));
                innerSerializer.Serialize(writer, node);
            }
        }
}

上面的代碼顯示了序列化代碼,省略了反序列化,因為我認為不需要它來解決問題。

那么如何在反序列化之前編寫加密和解密的文件呢? 加密/解密應該發生在 memory (我不想先寫一個未加密的文件然后再讀回加密它)

編輯:使用“加密”我的意思是該文件不應該是人類可讀或不知道如何解密它的其他程序解析(對稱密鑰)

更新 1:

這是相同的實現,但有兩種方法支持 Unicode 編碼並可能緩解代碼分析問題。

static void SerializeToEncryptedXmlFile(object graph, string filePath)
{
    using (FileStream encryptedFileStream = File.Create(filePath))
    {
        using (AesManaged aesManaged = CreateAesManaged())
        {
            using
            (
                CryptoStream cryptoStream = new CryptoStream
                (
                    encryptedFileStream, CreateAesManaged().CreateEncryptor(), CryptoStreamMode.Write
                )
            )
            {
                using (StreamWriter unicodeStreamWriter = new StreamWriter(cryptoStream, Encoding.Unicode))
                {
                    {
                        new XmlSerializer(typeof(CharacterData)).Serialize(unicodeStreamWriter, CharacterData.RandomInstance);
                        // If you dont use a using statement for the cryptoStream,
                        // Don't forget to call FlushFinalBlock yourself
                        // Or you will have padding problems.
                        // cryptoStream.FlushFinalBlock();
                    }
                }
            }
        }
    }
}

public static TResult DeserializeFromEncryptedXmlFile<TResult>(string filePath)
{
    using (FileStream encryptedFileStream = File.OpenRead(filePath))
    {
        using (AesManaged aesManaged = CreateAesManaged())
        {
            using
            (
                CryptoStream cryptoStream = new CryptoStream
                (
                    encryptedFileStream, aesManaged.CreateDecryptor(), CryptoStreamMode.Read
                )
            )
            {
                using (StreamReader unicodeStreamReader = new StreamReader(cryptoStream))
                {
                    return (TResult)new XmlSerializer(typeof(CharacterData)).Deserialize(unicodeStreamReader);
                }
            }
        }
    }
}

用法如下:

SerializeToEncryptedXmlFile(CharacterData.RandomInstance, "c:\\temp\\enc.xml");
CharacterData instance = DeserializeFromEncryptedXmlFile<CharacterData>("c:\\temp\\enc.xml");

原始答案:

要實現完全加密,請將CryptoStream實例傳遞給 XmlSerializer。

這是一個使用 AesManaged 的示例,涵蓋了加密和解密。

注意:CharacterData 是一些 XML 可序列化 class ,這里不相關。

// Returns AesManaged with 256 bit key, 128 bit IV, PKCS7 padding and using CBC mode
private static AesManaged CreateAesManaged()
{
    return new AesManaged()
    {
        Key = Encoding.ASCII.GetBytes("This is the key%This is the key%"),
        IV = Encoding.ASCII.GetBytes("This is the IV%%")
    };
}

static void Main(string[] args)
{
    // Serialization / Encryption:
    using (FileStream encryptedFileStream = File.Create("C:\\temp\\enc.xml"))
    {
        using
        (
            CryptoStream cryptoStream = new CryptoStream
            (
                encryptedFileStream, CreateAesManaged().CreateEncryptor(), CryptoStreamMode.Write
            )
        )
        {
            new XmlSerializer(typeof(CharacterData)).Serialize(cryptoStream, CharacterData.RandomInstance);
            // If you dont use a using statement for the cryptoStream,
            // Don't forget to call FlushFinalBlock yourself
            // Or you will have padding problems.
            // cryptoStream.FlushFinalBlock();
        }
    }

    // De-Serialization / Decryption:
    using (FileStream encryptedFileStream = File.OpenRead("C:\\temp\\enc.xml"))
    {
        using
        (
            CryptoStream cryptoStream = new CryptoStream
            (
                encryptedFileStream, CreateAesManaged().CreateDecryptor(), CryptoStreamMode.Read
            )
        )
        {
            CharacterData instance = (CharacterData)new XmlSerializer(typeof(CharacterData)).Deserialize(cryptoStream);
        }
    }

    Console.ReadLine();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM