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