2009-07-06 96 views
7

Necesito dos métodos, uno para cifrar y otro para descifrar un archivo xml con una clave = "hello world", la clave hello world debe usarse para cifrar y descifrar el archivo xml. Estos métodos deberían funcionar en todas las máquinas !!! Cualquier método de encriptación servirá. contenidos de archivos XML siguientes:?C# Cifrar un archivo XML

<root> 
    <lic> 
     <number>19834209</number> 
     <expiry>02/02/2002</expiry> 
    </lic> 
</root> 

Pueden algunos Dame una muestra de la cuestión es la muestra de MSDN encyptions hacen un archivo XML encriptados, pero cuando descifrar en otro equipo no lo hace ejemplo work.For

Probé esta muestra: How to: Encrypt XML Elements with Asymmetric Keys, pero aquí hay algo de sesión y en otra máquina dice ¡phewf!

+1

Por favor enviar un breve ejemplo de su código, y qué es exactamente no funciona (por ejemplo, 'en la línea 12 aparece un error compilor 12345', o 'durante tiempo de ejecución Obtengo una SecurityException en la línea 15 '). – Treb

+1

datos incorrectos creados por la clase de cifrado ah, bien – abmv

+1

¿Necesita encriptar los datos para ocultarlos, o simplemente proteger los datos de los cambios? – sisve

Respuesta

13

Si desea la misma clave para cifrar y descifrar, debe utilizar un método simétrico (esa es la definición, en realidad). Aquí está el más cercano a su muestra (misma fuente). http://msdn.microsoft.com/en-us/library/sb7w85t6.aspx

La muestra publicada no funciona porque no están utilizando las mismas teclas. No solo en máquinas diferentes: ejecutar el programa en la misma máquina dos veces tampoco debería funcionar (no funcionó para mí), porque usan diferentes claves aleatorias cada vez.
intento de añadir este código después de crear su clave:

key = new RijndaelManaged(); 

string password = "Password1234"; //password here 
byte[] saltBytes = Encoding.UTF8.GetBytes("Salt"); // salt here (another string) 
var p = new Rfc2898DeriveBytes(password, saltBytes); //TODO: think about number of iterations (third parameter) 
// sizes are devided by 8 because [ 1 byte = 8 bits ] 
key.IV = p.GetBytes(key.BlockSize/8); 
key.Key = p.GetBytes(key.KeySize/8); 

Ahora el programa está utilizando el mismo vector clave e inicial, y cifrar y descifrar debería funcionar en todas las máquinas.
Además, considere cambiar el nombre de key a algorithm, de lo contrario, esto es muy engañoso. Diría que es un ejemplo malo y que no funciona bien de MSDN.

NOTA: PasswordDeriveBytes.GetBytes() ya no se utiliza debido a problemas graves (de seguridad) dentro de la clase PasswordDeriveBytes. El código anterior se ha reescrito para usar la clase más segura Rfc2898DeriveBytes en su lugar (PBKDF2 en lugar de PBKDF1). El código generado con el anterior usando PasswordDeriveBytes puede verse comprometido.

Consulte también: Recommended # of iterations when using PKBDF2-SHA256?

+0

Intenté esa muestra, si comento solo desencripto, luego encriptar y luego comentar encriptar y el descifrado no funciona? ¿Por qué? – abmv

+0

Gracias, maldito sean esos chicos msdn, bueno me salvaste el día. Gracias de nuevo por tu tiempo y recursos. – abmv

+1

Como si tuviera tiempo para entender todas estas cosas complejas de cifrado. De hecho, estaba tratando de entender leyendo MSDN, pero si no pueden explicarlo correctamente, ¿quién más puede hacerlo? No necesita comprender toda la teoría criptográfica para codificar un archivo. ¡Bueno, .net tiene clases y solo necesito usarlas para ahorrar mi tiempo! ¡Y te doy un ejemplo, al menos debería funcionar en diferentes máquinas! – abmv

4

sería más fresco si se ha utilizado una clave privada para firmar el elemento <lic> y se agrega el resultado al archivo (en un elemento > < de hash tal vez). Esto permitiría que todos puedan leer el archivo xml en caso de que su soporte necesite saber el número de licencia, o la fecha de caducidad, pero no pueden cambiar ningún valor sin la clave privada.

La clave pública necesaria para verificar la firma sería de conocimiento común.

Aclaración
firma de su código sólo lo protegerá contra los cambios, no mantendrá ninguna información en ella oculta. Su pregunta original menciona el cifrado, pero no estoy seguro de que sea un requisito para ocultar los datos, o simplemente protegerlo de la modificación.

Código de ejemplo: (Nunca publique PrivateKey.key. Los métodos ServerMethods solo son necesarios al firmar el archivo xml, los ClientMethods solo son necesarios al verificar el archivo xml.)

using System; 
using System.Diagnostics; 
using System.IO; 
using System.Security.Cryptography; 
using System.Text; 
using System.Xml; 

public static class Program { 
    public static void Main() { 
     if (!File.Exists("PublicKey.key")) { 
      // Assume first run, generate keys and sign document. 
      ServerMethods.GenerateKeyPair(); 

      var input = new XmlDocument(); 
      input.Load("input.xml"); 
      Debug.Assert(input.DocumentElement != null); 

      var licNode = input.DocumentElement["lic"]; 
      Debug.Assert(licNode != null); 

      var licNodeXml = licNode.OuterXml; 
      var signedNode = input.CreateElement("signature"); 
      signedNode.InnerText = ServerMethods.CalculateSignature(licNodeXml); 
      input.DocumentElement.AppendChild(signedNode); 

      input.Save("output.xml"); 
     } 

     if (ClientMethods.IsValidLicense("output.xml")) { 
      Console.WriteLine("VALID"); 
     } else { 
      Console.WriteLine("INVALID"); 
     } 
    } 

    public static class ServerMethods { 
     public static void GenerateKeyPair() { 
      var rsa = SharedInformation.CryptoProvider; 

      using (var keyWriter = File.CreateText("PublicKey.key")) 
       keyWriter.Write(rsa.ToXmlString(false)); 

      using (var keyWriter = File.CreateText("PrivateKey.key")) 
       keyWriter.Write(rsa.ToXmlString(true)); 
     } 

     public static string CalculateSignature(string data) { 
      var rsa = SharedInformation.CryptoProvider; 
      rsa.FromXmlString(File.ReadAllText("PrivateKey.key")); 

      var dataBytes = Encoding.UTF8.GetBytes(data); 
      var signatureBytes = rsa.SignData(dataBytes, SharedInformation.HashAlgorithm); 
      return Convert.ToBase64String(signatureBytes); 
     } 
    } 

    public static class ClientMethods { 
     public static bool IsValid(string data, string signature) { 
      var rsa = SharedInformation.CryptoProvider; 
      rsa.FromXmlString(File.ReadAllText("PublicKey.key")); 

      var dataBytes = Encoding.UTF8.GetBytes(data); 
      var signatureBytes = Convert.FromBase64String(signature); 
      return rsa.VerifyData(dataBytes, SharedInformation.HashAlgorithm, signatureBytes); 
     } 

     public static bool IsValidLicense(string filename) { 
      var doc = new XmlDocument(); 
      doc.Load(filename); 

      var licNode = doc.SelectSingleNode("/root/lic") as XmlElement; 
      var signatureNode = doc.SelectSingleNode("/root/signature") as XmlElement; 
      if (licNode == null || signatureNode == null) return false; 

      return IsValid(licNode.OuterXml, signatureNode.InnerText); 
     } 
    } 

    public static class SharedInformation { 
     public static int KeySize { 
      get { return 1024; } 
     } 

     public static string HashAlgorithm { 
      get { return "SHA512"; } 
     } 

     public static RSACryptoServiceProvider CryptoProvider { 
      get { return new RSACryptoServiceProvider(KeySize, new CspParameters()); } 
     } 
    } 
} 
+0

Probé dos muestras de msdn pero ... el problema es que puedo hacer que decíptimamente en una máquina diff. – abmv

3

En primer lugar, si desea utilizar la misma clave para cifrar y descifrar, usted debe buscar en criptografía simétrica. La criptografía asimétrica es cuando las claves para encriptar y desencriptar son diferentes. Para que lo sepas, RSA es asimétrico, TripleDES y Rijndael son simétricos. También hay otros, pero .NET no tiene implementaciones predeterminadas para ellos.

Aconsejaría estudiar el System.Security.Cryptography namespace. Y aprendiendo un poco sobre todo eso. Tiene todo lo que necesita para cifrar y descifrar archivos, así como para generar una contraseña. En particular, usted podría estar interesado en estas clases:

  • CryptoStream
  • PasswordDeriveBytes
  • RijndaelManaged

Hay también ejemplos para el uso en MSDN para cada uno de ellos. Puede usar estas clases para encriptar cualquier archivo, no solo XML. Sin embargo, si desea encriptar solo unos pocos elementos seleccionados, puede echar un vistazo al espacio de nombres System.Security.Cryptography.Xml. Veo que ya has encontrado un artículo al respecto. Sigue los enlaces en esa página y aprenderás más sobre esas clases.

2

esta es la forma de firmar digitalmente y verificar documentos XML Sign XML Documents

+0

también ver una de las preguntas similares que planteé aquí http://stackoverflow.com/questions/1031856/digitally-sign-parts-of-a-xml-document – Eros