How to create digitally signed Xml Message using standard ISO20022 in .net ( C# )?

心不动则不痛 提交于 2020-03-21 06:38:33

问题


My project needs integration with payment gateway. The project is built in .net ( c# ) To integrate the gateway i need to sign XML message digitally following ISO 20022 standard. I am using dot net library SignedXml of System.Security.Cryptography The sample format and my code is shown below :

Sample Code:

<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>

My code : When i try to run this adding reference with Unique Identifier,

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

I receive response as : Malformed reference element

Also if someone can help me in how to create Reference without URI attribute?

        {
            //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;
        }

来源:https://stackoverflow.com/questions/60318515/how-to-create-digitally-signed-xml-message-using-standard-iso20022-in-net-c-s

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!