接收方无法验证签名的 XML 消息
Posted
技术标签:
【中文标题】接收方无法验证签名的 XML 消息【英文标题】:Receiving side failing to validate signed XML message 【发布时间】:2020-06-28 21:26:35 【问题描述】:我正在尝试根据为我们的测试应用程序提供的规格表使用 C# 签署一些 XML。我们必须:
-
规范化消息。
使用摘要算法创建整个消息的摘要。
将摘要添加到签名信息元素。
规范化签名信息。
将私钥和规范化的签名信息输入到指定的签名算法中,生成数字签名。
将生成的数字签名添加到签名元素。
这是我目前拥有的。
public static XmlElement Sign(XmlDocument msgDoc)
XmlDsigExcC14NTransform transform = new XmlDsigExcC14NTransform();
transform.LoadInput(msgDoc);
msgDoc.Load(transform.GetOutput() as Stream);
var signedXml = new SignedXml(msgDoc)
SigningKey = Certificate.GetRSAPrivateKey(),
;
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
var reference = new Reference();
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform(true));
reference.AddTransform(new XmlDsigC14N11Transform()); // Custom transform
reference.Uri = string.Empty;
reference.DigestMethod = SignedXml.XmlDsigSHA256Url;
signedXml.SignedInfo.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
var keyInfoData = new KeyInfoX509Data();
keyInfoData.AddIssuerSerial(CertManager.Certificate.Issuer, CertManager.Certificate.SerialNumber);
keyInfoData.AddSubjectName(CertManager.Certificate.Subject);
keyInfo.AddClause(keyInfoData);
signedXml.KeyInfo = keyInfo;
signedXml.ComputeSignature();
XmlElement signature = signedXml.GetXml();
// This part until the return was done to ensure we get the 'ds' prefix.
// Code taken from: https://***.com/questions/30579938/generate-digital-signature-but-with-a-specific-namespace-prefix-ds
SetPrefix("ds", signature);
signedXml.LoadXml(signature);
signedXml.SignedInfo.References.Clear();
signedXml.ComputeSignature();
ReplaceSignature(signature, Convert.ToBase64String(signedXml.SignatureValue));
XmlNode signatureElement = msgDoc.ImportNode(signature, true);
return msgDoc.DocumentElement.InsertAfter(msgDoc.ImportNode(signature, true), msgDoc.DocumentElement.FirstChild) as XmlElement;
摘要算法为:http://www.w3.org/2001/04/xmlenc#sha256
规范化算法为:http://www.w3.org/2001/10/xml-exc-c14n#
我们使用了两个转换:http://www.w3.org/2000/09/xmldsig#enveloped-signature 和 http://www.w3.org/2006/12/xml-c14n11
我已经在另一端启用了跟踪,它应该验证消息,这似乎是跟踪日志中唯一出现故障的地方:
[SignedXml#0071d445, VerificationFailure] 验证检查 SignedInfo 失败。
我已确保签名过程中使用的Certificate
是我的私有证书,而另一方使用公共证书进行验证过程。
我还缺少什么?
编辑:
我们能够验证我们从他们那里收到的消息。我无法提供他们如何验证消息的任何代码,因为它没有提供给我们。
这是我们发送的示例:
<Message xmlns="urn:tch">
<AppHdr>
<head:Fr xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
<head:ID>
<head:MemberId>1234245</head:MemberId>
</head:ID>
</head:Fr>
<head:To xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
<head:ID>
<head:MemberId>123345345</head:MemberId>
</head:ID>
<head:Date xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">2020-03-16T22:03:24</head:Date>
<head:Sgntr xmlns:head="urn:iso:std:iso:20022:tech:xsd:head.001.001.01">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>fV61VLaSYGyW+G+LxZaLfGdOlAVmpJvusoJ792IKblw=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>xlg1Q4hdQoCo+x4rJKWn1UwLwdshonx0dg5Z0bIAsFuBWOJGyVescQBFEZEbUHcgLq2TQZT6PBhH3F2RR4aYTnc9IY0mHRq5rJEpVfXnQZdwCw7SIhkMMIOi5rAgQ5gdLmQlbLWFm8V4+1DTE7QWiCALEkarJQcdU4n9E2rGrSM48H1NFHHC+m8J5eHcGFyRcBwSF712ihGDNvweGhwneR4JeGxyQ3Dc1pSkzkr0oOJDY0vgwIuMZIMvl6Fh98D3QByDadZqFah88uv+TWZy01B9rdfhgCP7gdeiP9fof90jnitQ4c/3XksjieLbWQxWmQ1TPoRQswDuXf731T6kmw==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=ABC, DC=AAA, DC=BBB, DC=CCC</ds:X509IssuerName>
<ds:X509SerialNumber>75822323454364025267732697561489775234425345</ds:X509SerialNumber>
</ds:X509IssuerSerial>
<ds:X509SubjectName>E=something@somewhere.com, CN=ABC.com, OU=Internet Services, O=AAA, L=Someplace, S=somewhere, C=US</ds:X509SubjectName>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</head:Sgntr>
</AppHdr>
<TestMessage>
<mr:zzzz.002.001.01 xmlns:mr="urn:iso:std:iso:20022:tech:xsd:zzzz.002.001.01">
<mr:Ref>
<mr:Ref>20200316220315134567890122203156779</mr:Ref>
</mr:Ref>
</TestMessage>
</Message>
编辑:如果有人使用上述信息创建示例进行签名,我将接受答案。
【问题讨论】:
接收方可以验证你的证书链吗?他们的受信任证书存储中是否有颁发者证书(***证书颁发机构)? @OguzOzgul 是的。 该错误表示加密选项与解密选项不同。因此,您必须比较两端的选项并让他们同意。只看加密代码并没有帮助。 Fiddler 将显示发送端使用的选项,这将验证您是否发送了有效的签名 xml,但不会显示接收选项。 @jdweng 不知道你的意思 @Jimenemex 1. 你能验证你的签名吗? 2. 能否提供验证对方签名的代码? 3. 您能否在帖子中添加一个由您的Sign
方法签名的示例 XML 文件?
【参考方案1】:
为了修复接收方,我们将 X509SubjectName 节点中的 S= 替换为 ST=。
【讨论】:
以上是关于接收方无法验证签名的 XML 消息的主要内容,如果未能解决你的问题,请参考以下文章