8

我已经设法使用 MSDN 上的示例加密和解密 xml 文档。 http://msdn.microsoft.com/en-us/library/ms229744.aspxhttp://msdn.microsoft.com/en-us/library/ms229943.aspx

这一切都是根据 W3C XML 加密标准 (XML Enc) 完成的。

这一切都很好。我的问题是一个 xml 文档适用于 2 或 3 个收件人。我想用多个密钥(X509 证书公钥)加密相同的 xml,以便文档可以被多个收件人解密。

根据 W3C XML 加密标准,通过使用包含加密对称会话密钥的多个 EncryptionKey 元素,这一切都是可能的。

我找不到任何关于如何在.Net 中使用标准加密类来实现这一点的示例。

这必须在 .NET C# 中实现。

有没有办法在某处执行此操作或代码示例?

4

1 回答 1

5

EncryptedElement 类可以使用任意数量的 EncryptedKey。只要对方能够正确识别他们的 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));

生产

<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>
于 2013-07-10T20:37:40.463 回答