.NET: SignedXml - 使用变换算法 exc-c14n 签名 XML

5
我正在尝试使用C#和SignedXml类签署Xml(实际上是SOAP xml),签名阶段成功通过,但是当我尝试验证签名时,它告诉我签名无效。我所做的唯一更改是从我使用的MSDN示例中使用XmlDsigExcC14NTransform而不是转换XmlDsigEnvelopedSignatureTransform。如果我使用XmlDsigEnvelopedSignatureTransform,我将获得有效的签名。
这是我的签名代码:
 private static XmlDocument SignXml(XmlDocument doc)
             {
                 SignedXml signedXml = new SignedXml(doc);
                 signedXml.SigningKey = Certificate.PrivateKey;
    
                 Reference reference = new Reference();
                 reference.Uri = "";
                 
                 XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
                 //XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();

                 reference.AddTransform(env);
    
                 signedXml.AddReference(reference);
                 signedXml.ComputeSignature();
    
                 XmlElement signature = signedXml.GetXml();
                 doc.DocumentElement.AppendChild(signature);
                 doc.Save(SignedXmlPath);
                 return doc;
             }

上述代码将为我提供有效的签名,但如果我使用
XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();

替代

XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();

我将会得到一个无效的签名。
这是我的验证代码:
private static bool Verify(XmlDocument doc)
        {
            SignedXml signedDoc = new SignedXml(doc);
            XmlNodeList nodeList = doc.GetElementsByTagName(Constants.SignatureElement);

            signedDoc.LoadXml((XmlElement)nodeList[0]);
            return signedDoc.CheckSignature((RSA)Certificate.PublicKey.Key);
        }

有人能告诉我如何使用http://www.w3.org/2001/10/xml-exc-c14n#的转换算法进行签名吗?

先感谢您。

1个回答

10

在您的情况下,您需要使用XmlDsigEnvelopedSignatureTransform,因为您正在向要签名的元素中添加签名。

XmlDsigEnvelopedSignatureTransform会告诉SignedXml类在测试有效性之前从签名节点本身中删除签名。这是必需的,因为您在计算签名后添加了该元素。

您可以通过再次调用AddTransform来添加多个转换,方法如下:

XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
XmlDsigExcC14NTransform c14n = new XmlDsigExcC14NTransform();

reference.AddTransform(env);
reference.AddTransform(c14n);

然而,我认为你实际想要做的是将CanonicalizationMethod设置为c14n,而不是按照我上面的示例执行操作。

signedXml.SignedInfo.CanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
 - or - 
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;

谢谢Jan的回答。我现在明白了。 实际上,我需要对SOAP消息中的正文进行签名,然后将签名添加到SOAP信封中的安全头中。因此,如果我这样做,我就可以使用XmlDsigExcC14NTransform,因为Signature元素不会成为已签名元素的一部分。对吗? 再次感谢... - Mahmoud
1
谢谢。我有一个类似的情况,也需要:c14n.Algorithm = SignedXml.XmlDsigExcC14NTransformUrl; - Paul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接