We are validating the signature in XML responses (for Peppol). For this we are using the SignedXml (System.Security.Cryptography.Xml) class in C#. Which works fine, most of the times. For some XML responses, validation using SignedXML fails. The difference between the ones failing and not, seems to be usage of dynamic namespaces prefixes (ns1-ns5). When we use Chillkat's online tool for validation, they validate it as valid https://tools.chilkat.io/xmlDsigVerify
Below a simplified implementation of our code, and 1 succesful and 1 failing (public) url. Anyone knows how to solve this, using the SignedXml class?
internal class Program
{
static async Task Main()
{
var failingUrl = "http://neovici.test.peppol.holodeck-smp.com/iso6523-actorid-upis%3A%3A9925%3Abe0848934496/services/busdox-docid-qns%3A%3Aurn%3Afdc%3Apeppol%3Aend-user-statistics-report%3A1.1%3A%3AEndUserStatisticsReport%23%23urn%3Afdc%3Apeppol.eu%3Aedec%3Atrns%3Aend-user-statistics-report%3A1.1%3A%3A1.1";
var successUrl = "http://smp.peppol.org/iso6523-actorid-upis%3A%3A9925%3Abe0848934496/services/busdox-docid-qns%3A%3Aurn%3Afdc%3Apeppol%3Aend-user-statistics-report%3A1.1%3A%3AEndUserStatisticsReport%23%23urn%3Afdc%3Apeppol.eu%3Aedec%3Atrns%3Aend-user-statistics-report%3A1.1%3A%3A1.1";
await Validate(failingUrl);
await Validate(successUrl);
async Task Validate(string url)
{
try
{
var content = await new HttpClient().GetStringAsync(url);
var xmlDocument = new XmlDocument();
xmlDocument.PreserveWhitespace = true;
xmlDocument.LoadXml(content);
// Validate the XML signature
bool isValid = ValidateXmlSignature(xmlDocument);
if(isValid)
{
Console.WriteLine("✓ XML signature is VALID");
}
else
{
Console.WriteLine("✗ XML signature is INVALID");
}
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
static bool ValidateXmlSignature(XmlDocument xmlDoc)
{
// Find the Signature element in the XML document
var signatureNode = xmlDoc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#");
if(signatureNode.Count == 0)
{
Console.WriteLine("No signature found in the XML document.");
return false;
}
try
{
// Load the signature
var signedXml = new SignedXml(xmlDoc);
signedXml.LoadXml((XmlElement)signatureNode[0]);
// Verify the signature
bool isValid = signedXml.CheckSignature();
return isValid;
}
catch (Exception ex)
{
Console.WriteLine($"Error during signature validation: {ex.Message}");
return false;
}
}
}