Зашифрованный файл XML при использовании IXmlSerializable (c#) - PullRequest
0 голосов
/ 03 апреля 2020

Как я могу записать XML -файл, в который я сериализовал, используя IXmlSerializable в зашифрованном виде?

Я (де) сериализую свои данные (структура узлов, содержащих узлы, такие же, как папки файловой системы) в 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);
            }
        }
}

Приведенный выше код показывает код сериализации, десериализация опущена, потому что я не думаю, что это необходимо для решения проблемы.

Так как Могу ли я записать файл в зашифрованном виде и расшифровать его перед десериализацией? Шифрование / дешифрование должно происходить в памяти (я не хочу сначала записывать незашифрованный файл и читать его, чтобы зашифровать)

edit: «шифрование» означает, что файл не должен читаться человеком или разбирается другими программами, не зная, как его расшифровать (ключ симметри c)

1 Ответ

0 голосов
/ 03 апреля 2020

ОБНОВЛЕНИЕ 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 сериализуемый класс, который здесь не имеет отношения.

// 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...