2009-12-15 36 views
5

Estoy tratando de cifrar/descifrar un archivo XML. Encontré esta muestra para cifrar, pero no sé cómo descifrar? ¿Alguna idea? ¡Gracias!Cómo cifrar/descifrar un archivo 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"); 

Pero no sé cómo descifraría eso? ¿Algunas ideas? ¡Gracias!

+2

cheque esto: http://stackoverflow.com/questions/1086049/c-encrypt-an-xml-file – PRR

+0

¿Alguno de las respuestas a continuación le fue útil? Si es así, ¿puedes aceptar uno para que la pregunta ya no sea "sin respuesta"? –

Respuesta

8

Algo como esto:

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

Editar:

Sani Huttunen señalado que mi implementación estática anterior tiene un problema de rendimiento grave si va a cifrar múltiples piezas de datos utilizando la misma contraseña . Puede leer más sobre esto aquí: http://jmpstart.wordpress.com/2009/09/29/proper-use-of-rfc2898derivebytes/

Editar: una implementación no estática que es mucho más eficiente si necesita realizar múltiples cifrados/descifrados usando la misma contraseña (~ 32 ms originales ~ 1 ms nuevo).

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

¿Alguna ventaja/desventaja de esta solución interna sobre el estándar XML Encryption? – dtb

+0

Una ventaja sería que podría usar esto para encriptar/desencriptar cualquier cadena. Honestamente, no sé sobre los métodos utilizados anteriormente. Mi ejemplo requiere una contraseña o frase de contraseña que a primera vista no vi en el ejemplo anterior. Además, el ejemplo anterior solo parece encriptar los elementos XML y no todo el XML (podría ser solo su uso) –

+2

Existe un riesgo de rendimiento en su solución. Puede leer sobre esto aquí: http://jmpstart.wordpress.com/2009/09/29/proper-use-of-rfc2898derivebytes/ –

Cuestiones relacionadas