C# 如何加密/解密XML文件?

C# 如何加密/解密XML文件?,c#,xml,encryption,C#,Xml,Encryption,我正在尝试加密/解密XML文件。我找到了这个加密示例,但我不知道如何解密?有什么想法吗?谢谢 // Load this XML file System.Xml.XmlDocument myDoc = new System.Xml.XmlDocument(); myDoc.Load(@"c:\persons.xml"); // Get a specified element to be encrypted System

我正在尝试加密/解密XML文件。我找到了这个加密示例,但我不知道如何解密?有什么想法吗?谢谢

        // Load this XML file
        System.Xml.XmlDocument myDoc = new System.Xml.XmlDocument();
        myDoc.Load(@"c:\persons.xml");
        // Get a specified element to be encrypted
        System.Xml.XmlElement element = myDoc.GetElementsByTagName("Persons")[0] as System.Xml.XmlElement;

        // Create a new TripleDES key. 
        System.Security.Cryptography.TripleDESCryptoServiceProvider tDESkey = new System.Security.Cryptography.TripleDESCryptoServiceProvider();

        // Form a Encrypted XML with the Key
        System.Security.Cryptography.Xml.EncryptedXml encr = new System.Security.Cryptography.Xml.EncryptedXml();
        encr.AddKeyNameMapping("Deskey", tDESkey);

        // Encrypt the element data
        System.Security.Cryptography.Xml.EncryptedData ed = encr.Encrypt(element, "Deskey");

        // Replace the existing data with the encrypted data
        System.Security.Cryptography.Xml.EncryptedXml.ReplaceElement(element, ed, false);

        // saves the xml file with encrypted data
        myDoc.Save(@"c:\encryptedpersons.xml");
但我不知道该如何解密?有什么想法吗?谢谢

虽然is使用RSA而不是三元组,但还是有一个。

类似这样的东西:

public static class Encryption
{
    private const string InitVector = "T=A4rAzu94ez-dra";
    private const int KeySize = 256;
    private const int PasswordIterations = 1000; //2;
    private const string SaltValue = "d=?ustAF=UstenAr3B@pRu8=ner5sW&h59_Xe9P2za-eFr2fa&ePHE@ras!a+uc@";

    public static string Decrypt(string encryptedText, string passPhrase)
    {
        byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
        byte[] initVectorBytes = Encoding.UTF8.GetBytes(InitVector);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(passPhrase);
        string plainText;
        byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);

        Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
        byte[] keyBytes = password.GetBytes(KeySize / 8);

        RijndaelManaged rijndaelManaged = new RijndaelManaged { Mode = CipherMode.CBC };

        try
        {
            using (ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(keyBytes, initVectorBytes))
            {
                using (MemoryStream memoryStream = new MemoryStream(encryptedTextBytes))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                    {
                        //TODO: Need to look into this more. Assuming encrypted text is longer than plain but there is probably a better way
                        byte[] plainTextBytes = new byte[encryptedTextBytes.Length];

                        int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                        plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
                    }
                }
            }
        }
        catch (CryptographicException)
        {
            plainText = string.Empty; // Assume the error is caused by an invalid password
        }

        return plainText;
    }

    public static string Encrypt(string plainText, string passPhrase)
    {
        string encryptedText;
        byte[] initVectorBytes = Encoding.UTF8.GetBytes(InitVector);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(passPhrase);
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
        byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);

        Rfc2898DeriveBytes password = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
        byte[] keyBytes = password.GetBytes(KeySize / 8);

        RijndaelManaged rijndaelManaged = new RijndaelManaged {Mode = CipherMode.CBC};

        using (ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(keyBytes, initVectorBytes))
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                    cryptoStream.FlushFinalBlock();

                    byte[] cipherTextBytes = memoryStream.ToArray();
                    encryptedText = Convert.ToBase64String(cipherTextBytes);
                }
            }
        }

        return encryptedText;
    }
}
编辑:

Sani Huttunen指出,如果要使用同一密码加密多个数据段,则上面的静态实现会出现严重的性能问题。您可以在此处阅读更多信息:

编辑:一种非静态实现,如果您需要使用同一密码(约32ms原始密码~1ms新密码)执行多个加密/解密,则该实现效率更高


与标准XML加密相比,这种自主开发的解决方案有什么优点/缺点?一个优点是您可以使用它来加密/解密任何字符串。老实说,我不知道上面使用的方法。我的示例确实需要密码或密码短语,但乍一看,我在上面的示例中没有看到。此外,上面的示例似乎只加密XML元素,而不是整个XML(可能只是用法),解决方案中存在性能缺陷。你可以在这里读到:谢谢你的提醒。在我当前的实现中,每次使用方法时密码很可能不同,因此每次使用新的
Rfc2898DeriveBytes
静态实现几乎都是一个要求:-)Ok。那么如何加密xml文件呢?与标准xml加密相比,使用此方法加密/解密是否切实可行?请检查以下问题:下面的答案对您有帮助吗?如果是这样的话,你能接受这样的问题就不会再“无人回答”了吗?
public class SimpleEncryption
{
    #region Constructor
    public SimpleEncryption(string password)
    {
        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
        byte[] saltValueBytes = Encoding.UTF8.GetBytes(SaltValue);

        _DeriveBytes = new Rfc2898DeriveBytes(passwordBytes, saltValueBytes, PasswordIterations);
        _InitVectorBytes = Encoding.UTF8.GetBytes(InitVector);
        _KeyBytes = _DeriveBytes.GetBytes(32);
    }
    #endregion

    #region Private Fields
    private readonly Rfc2898DeriveBytes _DeriveBytes;
    private readonly byte[] _InitVectorBytes;
    private readonly byte[] _KeyBytes;
    #endregion

    private const string InitVector = "T=A4rAzu94ez-dra";
    private const int PasswordIterations = 1000; //2;
    private const string SaltValue = "d=?ustAF=UstenAr3B@pRu8=ner5sW&h59_Xe9P2za-eFr2fa&ePHE@ras!a+uc@";

    public string Decrypt(string encryptedText)
    {
        byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);
        string plainText;

        RijndaelManaged rijndaelManaged = new RijndaelManaged { Mode = CipherMode.CBC };

        try
        {
            using (ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(_KeyBytes, _InitVectorBytes))
            {
                using (MemoryStream memoryStream = new MemoryStream(encryptedTextBytes))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                    {
                        //TODO: Need to look into this more. Assuming encrypted text is longer than plain but there is probably a better way
                        byte[] plainTextBytes = new byte[encryptedTextBytes.Length];

                        int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                        plainText = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
                    }
                }
            }
        }
        catch (CryptographicException exception)
        {
            plainText = string.Empty; // Assume the error is caused by an invalid password
        }

        return plainText;
    }

    public string Encrypt(string plainText)
    {
        string encryptedText;
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

        RijndaelManaged rijndaelManaged = new RijndaelManaged {Mode = CipherMode.CBC};

        using (ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(_KeyBytes, _InitVectorBytes))
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                    cryptoStream.FlushFinalBlock();

                    byte[] cipherTextBytes = memoryStream.ToArray();
                    encryptedText = Convert.ToBase64String(cipherTextBytes);
                }
            }
        }

        return encryptedText;
    }
}