2013-07-03 9 views
7

Sono riuscito a crittografare e decrittografare documenti xml utilizzando esempi su MSDN. http://msdn.microsoft.com/en-us/library/ms229744.aspx e http://msdn.microsoft.com/en-us/library/ms229943.aspxCodifica e decrittografia XML per più destinatari con certificati X509

Questo è tutto fatto secondo lo standard W3C crittografia XML (XML Enc).

Funziona tutto bene. Il mio problema è che un documento xml è destinato a 2 o 3 destinatari. Voglio crittografare lo stesso xml con più chiavi (chiave pubblica del certificato X509) in modo che il documento possa essere decifrato da più destinatari.

Questo è tutto possibile in base allo standard di crittografia XML W3C utilizzando più elementi EncryptionKey che contengono la chiave di sessione simmetrica crittografata.

Non sono riuscito a trovare alcun esempio su come ottenere questo in .Net utilizzando classi di crittografia standard.

Questo deve essere implementato in .NET C#.

C'è un modo per fare questo esempio di codice o da qualche parte?

+0

Benvenuti in Stackoverflow, e grazie per la domanda interessante. Speriamo che qualcuno con una certa conoscenza di .NET possa rispondere. Nota che dovresti sempre includere un tag della lingua. Non è necessario inserire la lingua nel titolo. –

+0

Non sono nemmeno uno sviluppatore C#, ma penso che Stackoverflow dovrebbe sapere questo ... –

+0

Non penso sia una buona idea: http://arstechnica.com/business/2011/10/researchers-break-w3c-encryption -standard-per-xml /, ecco la [carta] (http://www.nds.ruhr-uni-bochum.de/media/nds/veroeffentlichungen/2011/10/22/HowToBreakXMLenc.pdf). –

risposta

4

La classe EncryptedElement può richiedere quante chiavi Encrypted desiderate. Fino a quando l'altra parte in grado di identificare correttamente il loro EncryptedKey (utilizzando il destinatario o gli elementi KeyInfoName), non dovreste avere alcun problema:

// example xml 
XmlDocument xdoc = new XmlDocument(); 
xdoc.PreserveWhitespace = true; 
xdoc.LoadXml(@"<root><encryptme>hello world</encryptme></root>"); 

var elementToEncrypt = (XmlElement)xdoc.GetElementsByTagName("encryptme")[0]; 

// keys 
// rsa keys would normally be pulled from a store 
RSA rsaKey1 = new RSACryptoServiceProvider(); 
RSA rsaKey2 = new RSACryptoServiceProvider(); 
var publicKeys = new[] { rsaKey1, rsaKey2 }; 

string sessKeyName = "helloworldkey"; 
var sessKey = new RijndaelManaged() { KeySize = 256 }; 

// encrypt 
var encXml = new EncryptedXml(); 
var encryptedElement = new EncryptedData() 
{ 
    Type = EncryptedXml.XmlEncElementUrl, 
    EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url), 
    KeyInfo = new KeyInfo() 
}; 
encryptedElement.CipherData.CipherValue = encXml.EncryptData(elementToEncrypt, sessKey, false); 
encryptedElement.KeyInfo.AddClause(new KeyInfoName(sessKeyName)); 

// encrypt the session key and add keyinfo's 
int keyID = 0; 
foreach (var pk in publicKeys) 
{ 
    var encKey = new EncryptedKey() 
    { 
     CipherData = new CipherData(EncryptedXml.EncryptKey(sessKey.Key, pk, false)), 
     EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url), 
     Recipient = string.Format("recipient{0}@foobar.com", ++keyID), 
     CarriedKeyName = sessKeyName, 
    }; 
    encKey.KeyInfo.AddClause(new KeyInfoName(encKey.Recipient)); 
    encryptedElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(encKey)); 
} 

// update the xml 
EncryptedXml.ReplaceElement(elementToEncrypt, encryptedElement, false); 

// show the result 
Console.Write(xdoc.InnerXml); 
Console.ReadLine(); 
Console.WriteLine(new string('-', 80)); 

produce

<root> 
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"> 
     <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /> 
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 
      <KeyName>helloworldkey</KeyName> 
      <EncryptedKey Recipient="[email protected]" xmlns="http://www.w3.org/2001/04/xmlenc#"> 
       <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> 
       <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 
        <KeyName>[email protected]</KeyName> 
       </KeyInfo> 
       <CipherData> 
        <CipherValue>bmVT4SuAgWto6NJoTnUhrwaQ5/bWx39WKfs8y/QEQbaEBqdvl2Wa3woQGZxfigZ2wsWZQJFW0YGMII0W6AATnsqGOOVEbdGxmnvXRISiRdhcyNHkHot0kDK987y446ws5CZQQuz8inGq/SNrhiK6RyVnBE4ykWjrJyIS5wScwqA=</CipherValue> 
       </CipherData> 
       <CarriedKeyName>helloworldkey</CarriedKeyName> 
      </EncryptedKey> 
      <EncryptedKey Recipient="[email protected]" xmlns="http://www.w3.org/2001/04/xmlenc#"> 
       <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> 
       <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 
        <KeyName>[email protected]</KeyName> 
       </KeyInfo> 
       <CipherData> 
        <CipherValue>oR8NPTm1NasWeDXBjayLk+p9/5RTWOZwNJHUMTQpZB9v1Aasi75oSjGqSqN0HMTiviw6NWz8AvHB9+i08L4Hw8JRDLxZgjaKqTGu31wXmM3Vc0CoYQ15AWMZN4q4tSxDhwuT8fp9SN+WFBm+M3w3bcPoooAazzDHK3ErzfXzYiU=</CipherValue> 
       </CipherData> 
       <CarriedKeyName>helloworldkey</CarriedKeyName> 
      </EncryptedKey> 
     </KeyInfo> 
     <CipherData> 
      <CipherValue>ohjWIEFf2WO6v/CC+ugd7uxEKGJlxgdT9N+t3MhoTIyXHqT5VlknWs0XlAhcgajkxKFjwVO3p413eRSMTLXKCg==</CipherValue> 
     </CipherData> 
    </EncryptedData> 
</root> 

Per decifrare il documento, è necessario fornire una mappatura tra il nome della chiave e la chiave privata del certificato:

// Decrypt 
string myKeyName = "[email protected]"; 

// specify we want to use the key for recipient1 
var encryptedDoc = new EncryptedXml(xdoc); 
encryptedDoc.AddKeyNameMapping(myKeyName, rsaKey1); 
encryptedDoc.Recipient = myKeyName; 

// Decrypt the element. 
encryptedDoc.DecryptDocument(); 

// show the result 
Console.Write(xdoc.InnerXml); 
Console.ReadLine(); 

Risultato:

<root><encryptme>hello world</encryptme></root> 
+1

Aspetterò un verdetto del richiedente originale, ma questo sembra buono. Sono un po 'sorpreso dagli spazi dei nomi (digsig?), Ma due destinatari nel 'SignedInfo' ... Dovrebbe esserlo. –

+0

Questo è molto simile alla soluzione che ho provato, ma ottengo un'eccezione se provo a decifrare usando il 2 ° nome chiave invece del 1 °. Ho provato il tuo codice e sembra avere lo stesso problema. – RogerN

+1

@RogerN, sembra che mi mancasse un elemento KeyInfo. Devi anche specificare il campo Destinatario sull'oggetto EncryptedXml durante la decrittografia. Dovrebbe essere risolto ora. – Mitch