XML Signature incorrectly calculated - namespace declaration creates issues

  • Thread starter Thread starter ChristopheVer
  • Start date Start date
C

ChristopheVer

Guest
hello,

We're facing a bug in our application when we try to sign an XML message. The bug only occurs when we declare the namespaces of the XML Message inside an XML Element. For these messages we receive an invalid SignatureValue while the DigestValue is correct. We have two "flavors" of the namespace declaration in our XML Messages and we have to respect that. See the structure in the flowing messages. The difference is in the declaration of the head namespace.

1/

<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns="http://www.w3.org/2001/XMLSchema-instance" xmlns:a="myNamespace" xmlns:head="myHeader">
<Header>
<head:elementA>someInfo</head:elementA>
<head:signature></head:signature>
</Header>
<Data>
<a:DataEntry>some data</a:DataEntry>
<a:DataEntry>some data</a:DataEntry>
</Data>
</Message>

2/

<?xml version="1.0" encoding="UTF-8"?>
<Message xmlns="http://www.w3.org/2001/XMLSchema-instance" xmlns:a="myNamespace">
<Header>
<head:elementA xmlns:head="myHeader">someInfo</head:elementA>
<head:signature xmlns:head="myHeader"></head:signature>
</Header>
<Data>
<a:DataEntry>some data</a:DataEntry>
<a:DataEntry>some data</a:DataEntry>
</Data>
</Message>



We use two transformers in the generation of our signature: XmlDsigEnvelopedSignatureTransform and XmlDsigC14NTransform. Enveloped because we are going to append the generated signature in the element head:Signature. The code is more or less like this (I've abstracted it a bit):


XmlDocument currentMessageDocument = new XmlDocument();
currentMessageDocument.PreserveWhitespace = false;
currentMessageDocument.LoadXml(theXMLMessage);

SignedXml signedMessage = new SignedXml(currentMessageDocument);
Reference reference = new Reference();
reference.Uri = string.Empty;
reference.DigestMethod = XmlSignatureConstants.Sha256DigestMethodUri;
XmlDsigEnvelopedSignatureTransform envelopeTransform = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(envelopeTransform);
XmlDsigC14NTransform secondTransform = new XmlDsigC14NTransform();
reference.AddTransform(secondTransform);
secondTransform.Algorithm = XmlSignatureConstants.XmlDsigC14N2006TransformUri;
signedMessage.AddReference(reference);

signedMessage.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl;
signedMessage.SignedInfo.SignatureMethod = XmlSignatureConstants.RsaSha256Uri;
KeyInfo keyinfo = new KeyInfo();
KeyInfoX509Data x509Data = new KeyInfoX509Data();
x509Data.AddSubjectName(subjectname);
x509Data.AddIssuerSerial(serialNumber);
keyinfo.AddClause(x509Data);
signedMessage.KeyInfo = keyinfo;

signedMessage.ComputeSignature();

// This is specific to, signature has to look like that...
XmlElement signedMessageElement = signedMessage.GetXml();
XmlNamespaceManager nsMgr = new XmlNamespaceManager(currentMessageDocument.NameTable);
nsMgr.AddNamespace("dsig", "XML-Signature Syntax and Processing");
XmlNode x509DataNode = signedMessageElement.SelectSingleNode("dsig:KeyInfo/dsig:X509Data", nsMgr);
List<XmlNode> existingx509Nodes = x509DataNode.ChildNodes.Cast<XmlNode>().ToList();
x509DataNode.RemoveAll();
List<XmlNode> existingSubjectNameNodes = existingx509Nodes.Where(n => n.LocalName == "X509SubjectName").ToList();
List<XmlNode> existingIssuerSerialNodes = existingx509Nodes.Where(n => n.LocalName == "X509IssuerSerial").ToList();
List<XmlNode> existingSubjectAndIssuerSerialNodes = existingSubjectNameNodes.Concat(existingIssuerSerialNodes).ToList();
foreach (var subjectOrIssuerNode in existingSubjectAndIssuerSerialNodes.Concat(existingx509Nodes.Except(existingSubjectAndIssuerSerialNodes)))
{
x509DataNode.AppendChild(subjectOrIssuerNode);
}
XmlNode importedSignatureNode = currentMessageDocument.ImportNode(signedMessageElement, true);

XmlNode signatureNode = FindSignatureNode(theXMLMessage);
signatureNode.AppendChild(importedSignatureNode.OuterXml);

return theXMLMessage;


This code works for the messages where the namespace declaration is done in the root (number 1). But when we do the same for the other XML Message (2), the signatureValue is incorrect. The DigestValue of the signature is correct in both cases if we compare it with another tool that generates the XML Signatures.

So DigestValues are always correct but the SignatureValue is incorrect when we use the XML Message with the namespace declaration inside the XML Element Signature. When we decide to move the namespace declaration up to root level like XML Message 1, it works. But like I said, we cannot do this.

Any fresh ideas?

Continue reading...
 
Back
Top