简体   繁体   English

使用X509证书对多个收件人进行XML加密和解密

[英]XML encryption and decryption for multiple recipients with X509 certificates

I have managed to encrypt and decrypt xml documents using examples on MSDN. 我已经设法使用MSDN上的示例加密和解密xml文档。 http://msdn.microsoft.com/en-us/library/ms229744.aspx and http://msdn.microsoft.com/en-us/library/ms229943.aspx http://msdn.microsoft.com/en-us/library/ms229744.aspxhttp://msdn.microsoft.com/en-us/library/ms229943.aspx

This is all done according to the W3C XML encryption standard(XML Enc). 这都是根据W3C XML加密标准(XML Enc)完成的。

It all works good. 这一切都很好。 My problem is that one xml document is intended for 2 or 3 recipients. 我的问题是一个xml文档适用于2或3个收件人。 I want to encrypt same xml with multiple keys (X509 certificate public key) so that document could be decrypted by multiple recipients. 我想用多个密钥(X509证书公钥)加密相同的xml,以便多个收件人可以解密文档。

This is all possible according to the W3C XML encryption standard by using multiple EncryptionKey elements that contain encrypted symmetric session key. 根据W3C XML加密标准,通过使用包含加密对称会话密钥的多个EncryptionKey元素,这一切都是可能的。

I couldn't find any example on how to achieve this in .Net using standard cryptography classes. 我找不到任何关于如何使用标准加密类在.Net中实现此目的的示例。

This must be implemented in .NET C#. 这必须在.NET C#中实现。

Is there a way to do this or code example somewhere? 有没有办法在某处做这个或代码示例?

The EncryptedElement class can take as many EncryptedKeys as you want. EncryptedElement类可以根据需要使用尽可能多的EncryptedKeys。 As long as the other party can correctly identify their EncryptedKey (using the Recipient or the KeyInfoName elements), you should not have any problems: 只要对方能够正确识别他们的EncryptedKey(使用Recipient或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));

Produces 产生

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

To decrypt the document, you must provide a mapping between the key name and the private key of the certificate: 要解密文档,您必须提供密钥名称和证书私钥之间的映射:

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

Result: 结果:

<root><encryptme>hello world</encryptme></root>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM