Шифрование и расшифровка XML для нескольких получателей с сертификатами X509
мне удалось зашифровать и расшифровать xml-документы, используя примеры на MSDN. http://msdn.microsoft.com/en-us/library/ms229744.aspx и http://msdn.microsoft.com/en-us/library/ms229943.aspx
все это делается в соответствии со стандартом шифрования W3C XML (XML Enc).
все работает хорошо. Моя проблема в том, что один xml-документ предназначен для 2 или 3 получателей. Я хочу зашифровать тот же xml с несколькими ключами (сертификат x509 public ключ), чтобы документ мог быть расшифрован несколькими получателями.
Это все возможно в соответствии со стандартом шифрования W3C XML с помощью нескольких элементов EncryptionKey, которые содержат зашифрованный симметричный ключ сеанса.
Я не мог найти никакого примера о том, как достичь этого в .Net, используя стандартные классы криптографии.
Это должно быть реализовано в .NET C#.
есть ли способ сделать это или где-то пример кода?
1 ответов
класс EncryptedElement может принимать столько EncryptedKeys, сколько вы хотите. Пока другая сторона может правильно идентифицировать свой EncryptedKey (используя получателя или элементы KeyInfoName), у вас не должно быть никаких проблем:
// 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));
производит
<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="recipient1@foobar.com" 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>recipient1@foobar.com</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>bmVT4SuAgWto6NJoTnUhrwaQ5/bWx39WKfs8y/QEQbaEBqdvl2Wa3woQGZxfigZ2wsWZQJFW0YGMII0W6AATnsqGOOVEbdGxmnvXRISiRdhcyNHkHot0kDK987y446ws5CZQQuz8inGq/SNrhiK6RyVnBE4ykWjrJyIS5wScwqA=</CipherValue>
</CipherData>
<CarriedKeyName>helloworldkey</CarriedKeyName>
</EncryptedKey>
<EncryptedKey Recipient="recipient2@foobar.com" 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>recipient2@foobar.com</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>
для расшифровки документа необходимо указать сопоставление между именем ключа и закрытым ключом сертификата:
// Decrypt
string myKeyName = "recipient1@foobar.com";
// 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();
результат:
<root><encryptme>hello world</encryptme></root>