2009-12-15 128 views
5

我想加密/解密一个XML文件。我发现这个样本进行加密,但我不知道如何解密?任何想法?谢谢!如何加密/解密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"); 

但我不知道如何解密?有任何想法吗?谢谢!

+2

检查: http://stackoverflow.com/questions/1086049/c-encrypt-an-xml-file – PRR 2009-12-15 05:31:14

+0

难道以下任何帮助你的答案?如果这样你能接受一个,所以这个问题不再是“未答复”了吗? – 2009-12-17 19:07:54

回答

8

事情是这样的:

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 = "[email protected]=ner5sW&h59_Xe9P2za-eFr2fa&[email protected][email protected]"; 

    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; 
    } 
} 

编辑:

撒尼Huttunen指出,我上面的静态实现了,如果你会使用相同的密码来加密数据的多条严重的性能问题。你可以阅读更多关于它在这里:http://jmpstart.wordpress.com/2009/09/29/proper-use-of-rfc2898derivebytes/

编辑:非静态的实现,是更为有效的,如果你需要使用相同的密码(〜原为32ms〜1ms的新)执行多个加密/的解密。

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 = "[email protected]=ner5sW&h59_Xe9P2za-eFr2fa&[email protected][email protected]"; 

    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; 
    } 
} 
+1

这个本土解决方案在标准XML加密方面的优势/劣势是什么? – dtb 2009-12-15 05:01:11

+0

一个好处是你可以用它来加密/解密任何字符串。老实说,我不知道上面使用的方法。我的例子确实需要密码或密码,乍一看我没有在上面的例子中看到。此外,上面的示例似乎仅对XML元素进行加密,而不是对整个XML进行加密(可能只是使用) – 2009-12-15 05:08:53

+2

解决方案中存在性能问题。你可以在这里阅读它:http://jmpstart.wordpress.com/2009/09/29/proper-use-of-rfc2898derivebytes/ – 2009-12-15 05:17:42