读/写加密的xml

时间:2012-07-16 16:51:40

标签: c# xml serialization encryption

在我尝试加密/解密之前,我可以阅读写入我的序列化类...这里是我的代码片段:

public class ShelfCache
{
    public Shelf Data;
    public ShelfCache()
    {
        Data = new Shelf();
    }

    public void Write(string Filename)
    {
        XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
        TextWriter xslWriter = new StreamWriter(Filename);
        xsl.Serialize(xslWriter, Data);
        xslWriter.Flush();
        xslWriter.Close();
    }

    public void Read(string Filename)
    {
        Data = new Shelf();
        XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
        TextReader xslReader = new StreamReader(Filename);
        Data = (Shelf)xsl.Deserialize(xslReader);
        xslReader.Close();
    }

    public void WriteEncrypted(string Filename, string EncryptionKey = "")
    {
        string _Key = EncryptionKey + Environment.ExpandEnvironmentVariables("%USERNAME%%COMPUTERNAME%123456789ABCDEF0123456789abcdef").Substring(0, 32);
        string _IV = Environment.ExpandEnvironmentVariables("%COMPUTERNAME%123456789abcdef").Substring(0, 16);
        byte[] Key = Encoding.UTF8.GetBytes(_Key);
        byte[] IV = Encoding.UTF8.GetBytes(_IV);

        FileStream CacheStream = new FileStream(Filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
        RijndaelManaged CryptoProvider = new RijndaelManaged();
        ICryptoTransform CacheTransform = CryptoProvider.CreateEncryptor(Key, IV);
        CryptoStream EncryptionStream = new CryptoStream(CacheStream, CacheTransform, CryptoStreamMode.Write);
        XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
        xsl.Serialize(EncryptionStream, Data);
        EncryptionStream.Flush();
        CacheStream.Close();
    }

    public void ReadEncrypted(string Filename, string EncryptionKey = "")
    {
        string _Key = EncryptionKey + Environment.ExpandEnvironmentVariables("%USERNAME%%COMPUTERNAME%123456789ABCDEF0123456789abcdef").Substring(0, 32);
        string _IV = Environment.ExpandEnvironmentVariables("%COMPUTERNAME%123456789abcdef").Substring(0, 16);
        byte[] Key = Encoding.UTF8.GetBytes(_Key);
        byte[] IV = Encoding.UTF8.GetBytes(_IV);

        FileStream CacheStream = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
        RijndaelManaged CryptoProvider = new RijndaelManaged();
        ICryptoTransform CacheTransform = CryptoProvider.CreateEncryptor(Key, IV);
        CryptoStream DecryptionStream = new CryptoStream(CacheStream, CacheTransform, CryptoStreamMode.Read);
        XmlSerializer xsl = new XmlSerializer(typeof(Shelf));
        Data = (Shelf)xsl.Deserialize(DecryptionStream);
        CacheStream.Close();
    }

}

我得到异常“XML文档中存在错误(11)。”内部异常“根级别的数据无效。第1行,位置1”在线:

        Data = (Shelf)xsl.Deserialize(DecryptionStream);

1 个答案:

答案 0 :(得分:1)

这就是我最终做的事情(我不喜欢这个解决方案,但它确实有效)......

public class ShelfCache
{
    public Shelf Data;

    public ShelfCache()
    {
        Data = new Shelf();
    }

    public void Write(string Filename)
    {           
        XmlSerializer CacheSerializer = new XmlSerializer(typeof(Shelf));
        TextWriter CacheWriter = new StreamWriter(Filename);
        CacheSerializer.Serialize(CacheWriter, Data);
        CacheWriter.Flush();
        CacheWriter.Close();
    }

    public void Read(string Filename)
    {
        Data = new Shelf();
        XmlSerializer CacheSerializer = new XmlSerializer(typeof(Shelf));
        TextReader CacheReader = new StreamReader(Filename);
        Data = (Shelf)CacheSerializer.Deserialize(CacheReader);
        CacheReader.Close();
    }

    public void WriteEncrypted(string Filename, string EncryptionKey = "")
    {
        string TempFile = System.IO.Path.GetTempFileName();
        Write(TempFile);
        EncryptFile(TempFile, Filename, EncryptionKey);
        File.Delete(TempFile);
    }

    public void ReadEncrypted(string Filename, string EncryptionKey = "")
    {
        string TempFile = System.IO.Path.GetTempFileName();
        DecryptFile(Filename, TempFile, EncryptionKey);
        Read(TempFile);
        File.Delete(TempFile);
    }

    private RijndaelManaged GetEncryptor(string Key = "", string Salt = "")
    {
        Key += Environment.ExpandEnvironmentVariables("%USERNAME%");
        Salt += Environment.ExpandEnvironmentVariables("%COMPUTERNAME%");
        Rfc2898DeriveBytes derivedKey = new Rfc2898DeriveBytes(Key, Encoding.Unicode.GetBytes(Salt));
        RijndaelManaged rijndaelCSP = new RijndaelManaged();
        rijndaelCSP.Key = derivedKey.GetBytes(rijndaelCSP.KeySize / 8);
        rijndaelCSP.IV = derivedKey.GetBytes(rijndaelCSP.BlockSize / 8);
        return rijndaelCSP;
    }

    private void EncryptFile(string Source, string Target, string EncryptionKey)
    {
        RijndaelManaged EncryptionProvider = GetEncryptor(EncryptionKey);
        ICryptoTransform Encryptor = EncryptionProvider.CreateEncryptor();

        FileStream SourceStream = new FileStream(Source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
        byte[] SourceBytes = new byte[(int)SourceStream.Length];
        SourceStream.Read(SourceBytes, 0, (int)SourceStream.Length);
        FileStream TargetStream = new FileStream(Target, FileMode.Create, FileAccess.Write);
        CryptoStream EncryptionStream = new CryptoStream(TargetStream, Encryptor, CryptoStreamMode.Write);
        EncryptionStream.Write(SourceBytes, 0, (int)SourceStream.Length);
        EncryptionStream.FlushFinalBlock();

        EncryptionProvider.Clear();
        EncryptionStream.Close();
        SourceStream.Close();
        TargetStream.Close();
    }

    private void DecryptFile(string Source, string Target, string EncryptionKey)
    {
        RijndaelManaged EncryptionProvider = GetEncryptor(EncryptionKey);
        ICryptoTransform Decryptor = EncryptionProvider.CreateDecryptor();

        FileStream SourceStream = new FileStream(Source, FileMode.Open, FileAccess.Read);
        CryptoStream DecryptionStream = new CryptoStream(SourceStream, Decryptor, CryptoStreamMode.Read);
        byte[] SourceBytes = new byte[(int)SourceStream.Length];
        int DecryptionLength = DecryptionStream.Read(SourceBytes, 0, (int)SourceStream.Length);
        FileStream TargetStream = new FileStream(Target, FileMode.Create, FileAccess.Write);
        TargetStream.Write(SourceBytes, 0, DecryptionLength);
        TargetStream.Flush();

        EncryptionProvider.Clear();
        DecryptionStream.Close();
        SourceStream.Close();
        TargetStream.Close();
    }

}