2009-07-06 13 views
7

Ho bisogno di due metodi uno per crittografare e uno per decrittografare un file xml con una chiave = "ciao mondo", il mondo ciao chiave dovrebbe essere usato per crittografare e decifrare il file xml. Questi metodi dovrebbero funzionare su tutte le macchine !!! Qualsiasi metodo di crittografia funzionerà. Contenuto del file XML di seguito:?C# Criptare un file XML

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

Qualcuno può darmi un campione Il problema è l'encyptions campione MSDN fanno un file XML criptati ma quando ho decifro su un'altra macchina che non si work.For esempio

Ho provato questo esempio: How to: Encrypt XML Elements with Asymmetric Keys, ma qui c'è una sorta di sessione e su un'altra macchina si dice un pò di dati pessimi!

+1

Si prega di inviare un breve esempio di codice, e che cosa esattamente non funziona (ad esempio 'On line 12 ottengo un errore compilor 12345', o 'durante runtime Ottengo un SecurityException sulla riga 15 '). – Treb

+1

dati errati contenuti nella classe di codifica ah bene – abmv

+1

È necessario crittografare i dati per nasconderlo o semplicemente proteggere i dati dalle modifiche? – sisve

risposta

13

Se si desidera utilizzare la stessa chiave per crittografare e decrittografare, è necessario utilizzare un metodo simmetrico (che è la definizione, in realtà). Ecco quello più vicino al tuo campione (stessa fonte). http://msdn.microsoft.com/en-us/library/sb7w85t6.aspx

L'esempio registrato non funziona perché non utilizzano le stesse chiavi. Non solo su macchine diverse: eseguire il programma sulla stessa macchina due volte non dovrebbe funzionare (non ha funzionato per me), perché ogni volta usano chiavi casuali diverse.
prova ad aggiungere il codice dopo aver creato la chiave:

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

Ora il programma sta utilizzando lo stesso vettore chiave e iniziale e crittografare e decrittografare dovrebbe funzionare su tutte le macchine.
Inoltre, prendere in considerazione la possibilità di rinominare key in algorithm, in caso contrario è molto fuorviante. Direi che è un cattivo esempio non funzionante da MSDN.

NOTA: PasswordDeriveBytes.GetBytes() è stato sconsigliato a causa della (sicurezza) gravi problemi all'interno della classe PasswordDeriveBytes. Il codice precedente è stato riscritto per utilizzare invece la classe più sicura Rfc2898DeriveBytes (PBKDF2 anziché PBKDF1). Il codice generato con quanto sopra usando PasswordDeriveBytes potrebbe essere compromesso.

Consulta anche: Recommended # of iterations when using PKBDF2-SHA256?

+0

Ho provato quell'esempio, se commento solo decifrare, quindi criptare e quindi commentare encrypt e il decrypt non funziona? Perché? – abmv

+0

Grazie, maledetti ragazzi, beh, mi hai salvato la giornata. Grazie ancora per il tuo tempo e le tue risorse. – abmv

+1

Come se avessi il tempo di capire tutte queste complesse operazioni di crittografia. Stavo cercando di capire leggendo MSDN, ma se non riescono a spiegarlo correttamente, allora chi altri può. Non hai bisogno di capire l'intera Teoria Crittografica per codificare un file. Beh. Net ha classi e ho solo bisogno di usarle per risparmiare tempo! E io ti danno un esempio, quindi dovrebbe funzionare su macchine diverse! – abmv

4

sarebbe più fresco se si è utilizzato una chiave privata per firmare l'elemento <lic> e aggiunto il risultato al file (in un <hash> elemento forse). Ciò consentirebbe a tutti di leggere il file xml nel caso in cui il supporto debba conoscere il numero di licenza o la data di scadenza, ma non possono modificare alcun valore senza la chiave privata.

La chiave pubblica necessaria per verificare la firma sarebbe di dominio pubblico.

Chiarimento
firma il codice servirà solo a proteggerlo contro i cambiamenti, non mancherà di tenere tutte le informazioni in esso nascoste. La tua domanda originale menziona la crittografia, ma non sono sicuro che sia un requisito per nascondere i dati, o semplicemente proteggerli dalle modifiche.

Codice di esempio: (Non pubblicare mai PrivateKey.key. ServerMethods sono necessari solo quando si firma il file xml, ClientMethods sono necessari solo durante la verifica del file 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

Ho provato due esempi da msdn ma ... il problema è che posso farlo decifrare correttamente su una macchina di diff. – abmv

3

Prima di tutto, se si desidera utilizzare la stessa chiave per cifrare e decifrare, si dovrebbe guardare a crittografia simmetrica. La crittografia asimmetrica è quando le chiavi per la crittografia e la decrittografia sono diverse. Solo per sapere che - RSA è asimmetrico, TripleDES e Rijndael sono simmetrici. Ce ne sono anche altri, ma .NET non ha implementazioni predefinite per loro.

Consiglio di studiare lo System.Security.Cryptography namespace. E imparando un po 'su tutte quelle cose. Ha tutto il necessario per crittografare e decodificare i file, oltre a generare una password. In particolare, si potrebbe essere interessati a queste classi:

  • CryptoStream
  • PasswordDeriveBytes
  • RijndaelManaged

ci sono anche esempi per l'uso in MSDN per ciascuno di essi. È possibile utilizzare queste classi per crittografare qualsiasi file, non solo XML. Se tuttavia si desidera crittografare solo alcuni elementi, è possibile dare uno sguardo allo spazio dei nomi System.Security.Cryptography.Xml. Vedo che hai già trovato un articolo a riguardo. Continua a seguire i link su quella pagina e imparerai di più su quelle classi.

2

questo è il modo di firmare digitalmente e verificare i documenti XML Sign XML Documents

+0

anche vedere una delle domande simili che ho sollevato qui http://stackoverflow.com/questions/1031856/digitally-sign-parts-of-a-xml-document – Eros