.Net: SignedXml — подписание xml с алгоритмом преобразования exc-c14n

Я пытаюсь подписать Xml (фактически SOAP xml) на С#, используя ссылку SignedXml class, этап подписания проходит успешно, но когда я пытаюсь проверить подпись, она сообщает мне, что она недействительна. Единственное изменение, которое я сделал по сравнению с примером в 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#

Заранее спасибо.


person Mahmoud    schedule 06.12.2012    source источник


Ответы (1)


В вашем случае вам понадобится 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;
person Jan-Peter Vos    schedule 06.12.2012
comment
Спасибо Ян за ваш ответ. Теперь я понимаю. На самом деле мне нужно подписать тело в сообщении SOAP, а затем я добавлю подпись в заголовок безопасности в конверте SOAP. Поэтому, если я это сделаю, я смогу использовать XmlDsigExcC14NTransform, потому что тогда элемент Signature не будет частью подписанного. правильно? Спасибо еще раз... - person Mahmoud; 07.12.2012
comment
Спасибо. У меня был похожий случай и тоже понадобилось: c14n.Algorithm = SignedXml.XmlDsigExcC14NTransformUrl; - person Paul; 25.05.2016