【问题标题】:How to create digitally signed Xml Message using standard ISO20022 in .net ( C# )?如何在 .net ( C# ) 中使用标准 ISO20022 创建数字签名的 Xml 消息?
【发布时间】:2021-04-01 22:41:28
【问题描述】:

我的项目需要与支付网关集成。 该项目内置于 .net ( c# ) 要集成网关,我需要按照 ISO 20022 标准对 XML 消息进行数字签名。 我正在使用 System.Security.Cryptography 的点网库 SignedXml 示例格式和我的代码如下所示:

示例代码:

<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/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>eoXljsKRVEUPMMqrqjdtHyIUD4GyjeIsGPx8vVLey9g=</ds:DigestValue>
        </ds:Reference>
        <ds:Reference URI="#49e752ba-8e80-4be5-8538-67866c2e1dd9">
            <ds:Transforms>
                <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>n4pKHz5MvOPK7uDcdyFlxZrEz3kgtq6t56HcEdDmeyA=</ds:DigestValue>
        </ds:Reference>
        <ds:Reference>
            <ds:Transforms>
                <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <ds:DigestValue>ZH7NiLE0HlL8nIChNnauUXYugxZlX6rgUI2YMSrzSyE=</ds:DigestValue>
        </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue>
        KN6PPWZQ/C8AHexw+nqfX375S3rm4CyqjWxfzWcHGEpAfxE3j7RKArxq0Xx5ofnILJ0g5LlxKgNS
        YDJJ+HB/cc6S4LzWFFRbwL9U9fC8ZXNWk/Sf+4SSK/t/Aaz2TqYUDrpd4Q+qq8e+EMryI2sULRtC
        FxvBU/BRAAnnZhLBDQX3crSHU3ynaOSeicFbAaX1LuwCsKppqSZSFcq3MHgIQ4PBFFRlLtXVuQms
        I8ZYpSe2ZsxSlCwaSdNMXpQDunhbTQE464691W+kyBczVz37/jsCKy8q2AM5JA4sabHgMpO5NxsZ
        eK00sNKG+guRSTuMsZpdVaMZPjNI3aMxB+JHHw==
    </ds:SignatureValue>
    <ds:KeyInfo Id="49e752ba-8e80-4be5-8538-67866c2e1dd9">
        <ds:X509Data>
            <ds:X509SKI>
                udATCnB3DNmvJuBuZCU/NCOAxU0=
            </ds:X509SKI>
        </ds:X509Data>
    </ds:KeyInfo>
</ds:Signature>

我的代码: 当我尝试使用唯一标识符运行此添加引用时,

 Reference referenceKeyInfo = new Reference();
 referenceKeyInfo.Uri = "#"+keyInfo.Id;

我收到回复:Malformed reference element

如果有人可以帮助我如何创建没有 URI 属性的引用?

        {
            //Access certificate
            X509Certificate2 cert = null;

            X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            certStore.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certCollection = certStore.Certificates.Find(
                                       X509FindType.FindByThumbprint,
                                       "MY CERTIFICATE THUMBPRINT HERE",
                                       false);
            cert = certCollection[0];



            XmlDocument doc = new XmlDocument();
            XmlSerializer payloadserializer = new XmlSerializer(typeof(RequestPayload));
            var writer = new StringWriter();
            //serilize object to xml
            payloadserializer.Serialize(writer, requestPayload);
            string xml = writer.ToString();
            //load xml into XmlDocument
            doc.LoadXml(xml);

            //create object for xml signature and assign certificate private key to signature signing key
            SignedXml signedXml = new SignedXml(doc);
            signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
            /////Signature value
            signedXml.SigningKey = cert.PrivateKey;

            //create key info node of signature
            KeyInfo keyInfo = new KeyInfo();
            keyInfo.Id = Guid.NewGuid().ToString();//Id is uniq ID
            //// Reference Header element

            //create reference element of xml, for header and assign uri(default uri, uri="")
            Reference referenceHeader = new Reference();
            referenceHeader.Uri = "#header";
            referenceHeader.LoadXml(header);
            //create transofrm node for signature
            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
            //done canonicalisation on transform and allows a signer to create a digest
            XmlDsigExcC14NTransform headerC14n = new XmlDsigExcC14NTransform();
            //add transform to reference node before digest algorithm
            referenceHeader.AddTransform(env);
            referenceHeader.AddTransform(headerC14n);
            signedXml.AddReference(referenceHeader);

            //create reference element of xml, for KeyInfo and uri with #document, which will be replace by uniqId
            Reference referenceKeyInfo = new Reference();
            referenceKeyInfo.Uri = "#"+keyInfo.Id;
            XmlDsigExcC14NTransform keyInfoC14n = new XmlDsigExcC14NTransform();
            referenceKeyInfo.AddTransform(keyInfoC14n);
            signedXml.AddReference(referenceKeyInfo);

            ////reference document element
            //create reference element of xml, for document and uri is absent            
            Reference referenceDocument = new Reference();           
            //done canonicalisation on transform and allows a signer to create a digest
            XmlDsigExcC14NTransform documentC14n = new XmlDsigExcC14NTransform();
            //add transform to reference node before digest algorithm
            referenceDocument.AddTransform(documentC14n);
            signedXml.AddReference(referenceDocument);



            ////KeyInfo element of signature
            // create KeyInfo element then create X509 element and add subject key id
            KeyInfoX509Data keyInfoData = new KeyInfoX509Data();
            keyInfoData.AddSubjectKeyId("MY CERTIFICATE SUBJECT KEY ID HERE");
            keyInfo.AddClause(keyInfoData);
            signedXml.KeyInfo = keyInfo;

            // Compute the signature.
            signedXml.ComputeSignature();

            XmlElement xmlDigitalSignature = signedXml.GetXml();
            SetPrefix("ds", xmlDigitalSignature);
            string signatureXml = xmlDigitalSignature.OuterXml.ToString();
            requestPayload.AppHdr.Sgntr = signatureXml;
        }

【问题讨论】:

  • 我在测试智能卡时的第一个建议是使用 Windows 解锁卡,并在尝试在 c# 中解锁之前让所有读/写工作正常。在 Windows 中解锁后,该卡将保持解锁状态。通过这种方式,您可以测试您是否正确读取/写入卡。 XML 文件格式与 SOAP 格式非常相似,因此您可以使用 SOAP 代码。在以下帖子中查看我的答案:stackoverflow.com/questions/46722997/…
  • 感谢您的回复...我遵循了您的代码,但在使用 uri="UNIQUEIDENTIFIER" 创建参考元素并使用 null uri 时我仍然面临问题我已成功实现使用 uri 创建参考元素=""你能帮我解决这个问题吗
  • URI 是一个前缀,例如 (ds),带有一个 uri ("w3.org/2000/09/xmldsig#")。所以要获得前缀 ds,您可以使用 referenceHeader.Uri = "w3.org/2000/09/xmldsig#"; uri 需要在此代码之前定义。应该已经在 xml 中。
  • 您是否解决了 KeyInfo @PranitaChavan 的问题?如果是这样,你能分享你的解决方案吗?我目前在使用 KeyInfo 时遇到了同样的问题,并且没有办法解决它。

标签: c# .net payment-gateway digital-signature mastercard


【解决方案1】:

SignedXml 的默认实现不能与同时具有命名空间的 id 一起使用。

似乎解决此问题的唯一方法是创建SignedXml 的自定义子类并按照此答案https://stackoverflow.com/a/6467877/536546 的建议覆盖GetIdElement 方法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多