Как создать сообщение с цифровой подписью Xml, используя стандарт ISO20022 in. net (C#)? - PullRequest
0 голосов
/ 20 февраля 2020

Мой проект нуждается в интеграции с платежным шлюзом. Проект встроен. net (c#) Чтобы интегрировать шлюз, мне нужно подписать сообщение XML в цифровом виде в соответствии со стандартом ISO 20022. Я использую библиотеку dot net, подписанную Xml System.Security.Cryptography. Ниже приведен пример формата и мой код:

Пример кода:

<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;
        }
...