証明書が添付された署名付き XML をサードパーティから受け取りました。また、シリアル番号が同じであることを確認するために、この証明書のコピーをローカルに持っているので、ローカルにあるのと同じ証明書によって XML が署名されていることは確かです。
ただし、SignedXml.CheckSignature() は常に false を返すため、検証は常に失敗します。何故ですか?私が理解していることから、署名された XML には常に署名された証明書のコピーが含まれており、パラメーターのないメソッドはこの証明書に対して署名を検証しようとします。これは常に機能するはずではありませんか?
参考までに: ローカル証明書のコピーを使用した署名の検証も、すべての場合に失敗します。
2016年12月9日編集
さらに調べてみると、署名付き XML は 2 つの変換を使用して署名されていることがわかりますが、検証時に指定できる正規化方法は 1 つだけです。XML の例を以下に添付します。
https://blogs.msdn.microsoft.com/alejacma/2010/08/18/creating-signatures-with-signedxml-following-ebxml-standard/で言及されているように、cid で始まる参照によって問題が発生する可能性はありますか? これはかなり古い記事です。当時とは状況が変わっている可能性があります。
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/RECxml-c14n-20010315"></ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#envelopedsignature"></ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>RJ2QdODr5ADUs9RAR9aT8NFdqds=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="cid:ebxhmpayload111@example.com">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
<ds:DigestValue>j1BG/SCN4Z74inL530u2SYGWKtE=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>ZRLxNWAWqxvW1d9vdtZhQ3cII02NhUk7H8ugAML0cIrP0noebUMikAOuX6fNIVTvi4kLAeb3FfQqBJD6heRWrM0lMZsA0rIHVOtH3fc6JqwUWRuiS9zzuKIx5ah8O0yU1ZkeS5b6fTJtX36+idO5KvTZc2az7fpWhPLcrfcyT4A=
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>*redacted*</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
コード:
var xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = false;
xmlDoc.LoadXml(xmlData);
var signedXmlDoc = new SignedXml(xmlDoc);
var signatureNodeList = xmlDoc.GetElementsByTagName("Signature");
signedXmlDoc.LoadXml((XmlElement)signatureNodeList[0]);
var signingCertificate = new X509Certificate2(sender.SigningCertificate);
foreach (var ex in signingCertificate.Extensions)
{
if (ex.Oid.Value == "2.5.29.15")
{
var ext = (X509KeyUsageExtension)ex;
if (!ext.KeyUsages.HasFlag(X509KeyUsageFlags.NonRepudiation))
throw new CertificateException("The signing certificate does not support non-repudiation.");
}
}
var transmittedCert = new X509Certificate2(Convert.FromBase64String(xmlDoc.GetElementsByTagName("X509Certificate")[0].InnerText));
if (transmittedCert.SerialNumber != signingCertificate.SerialNumber)
throw new CertificateException("Serial numbers do not match. The message was signed by another certificate");
var validSignature = signedXmlDoc.CheckSignature();