dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.07k stars 4.69k forks source link

SignedXml cannot validate signature that contain XPath transforms #82363

Open petarpetrovt opened 1 year ago

petarpetrovt commented 1 year ago

Description

I have a few XML documents that have been signed using various tools, but their validation fails in .NET. However, these documents are deemed valid in tools such as the European Commission Digital Signature Service (DSS).

Reproduction Steps

Generate an enveloped XAdES signed XML document via DSS tool.

The transform that seems to not be supported.

<ds:Transform Algorithm="http://www.w3.org/2002/06/xmldsig-filter2">
  <dsig-filter2:XPath xmlns:dsig-filter2="http://www.w3.org/2002/06/xmldsig-filter2" Filter="subtract">/descendant::ds:Signature</dsig-filter2:XPath>
</ds:Transform>

The validation code.

XmlDocument document = new() { PreserveWhitespace = true };
document.Load("test-signed-xades-baseline-b.xml");
var signedXml = new SignedXml(document);
signedXml.LoadXml((XmlElement)document.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl)[0]!);
Console.WriteLine(signedXml.CheckSignature());

Expected behavior

The signature validation is successful.

Actual behavior

Unhandled exception. System.Security.Cryptography.CryptographicException: Unknown transform has been encountered.
   at System.Security.Cryptography.Xml.Reference.LoadXml(XmlElement value)
   at System.Security.Cryptography.Xml.SignedInfo.LoadXml(XmlElement value)
   at System.Security.Cryptography.Xml.Signature.LoadXml(XmlElement value)
   at System.Security.Cryptography.Xml.SignedXml.LoadXml(XmlElement value)

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

I have a signature produced by a Java application that uses a different XPath transform. This signature also cannot be validated.

<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
  <ds:XPath>not(ancestor-or-self::ds:Signature)</ds:XPath>
</ds:Transform>

Adding http://www.w3.org/TR/1999/REC-xpath-19991116 algorithm in SafeCanonicalizationMethods property allows to bypass IsSafeTransform check but then throws XPathException, maybe related to this #21451 issue.

signedXml.SafeCanonicalizationMethods.Add("http://www.w3.org/TR/1999/REC-xpath-19991116");
Unhandled exception. System.Xml.XPath.XPathException: Namespace prefix 'ds' is not defined.
   at MS.Internal.Xml.XPath.CompiledXpathExpr.UndefinedXsltContext.LookupNamespace(String prefix)
   at MS.Internal.Xml.XPath.BaseAxisQuery.SetXsltContext(XsltContext context)
   at MS.Internal.Xml.XPath.CompiledXpathExpr.SetContext(IXmlNamespaceResolver nsResolver)
   at System.Security.Cryptography.Xml.XmlDsigXPathTransform.GetOutput()
   at System.Security.Cryptography.Xml.TransformChain.TransformToOctetStream(Object inputObject, Type inputType, XmlResolver resolver, String baseUri)
   at System.Security.Cryptography.Xml.TransformChain.TransformToOctetStream(XmlDocument document, XmlResolver resolver, String baseUri)
   at System.Security.Cryptography.Xml.Reference.CalculateHashValue(XmlDocument document, CanonicalXmlNodeList refList)
   at System.Security.Cryptography.Xml.SignedXml.CheckDigestedReferences()
   at System.Security.Cryptography.Xml.SignedXml.CheckSignature(AsymmetricAlgorithm key)
   at System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey(AsymmetricAlgorithm& signingKey)
   at System.Security.Cryptography.Xml.SignedXml.CheckSignature()
ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-system-security, @vcsjones See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I have a few XML documents that have been signed using various tools, but their validation fails in .NET. However, these documents are deemed valid in tools such as the [European Commission Digital Signature Service (DSS)](https://ec.europa.eu/digital-building-blocks/DSS/webapp-demo/home). ### Reproduction Steps Generate an enveloped XAdES signed XML document via [DSS](https://ec.europa.eu/digital-building-blocks/DSS/webapp-demo/sign-a-document) tool. The transform that seems to not be supported. ```xml /descendant::ds:Signature ``` The validation code. ```csharp XmlDocument document = new() { PreserveWhitespace = true }; document.Load("test-signed-xades-baseline-b.xml"); var signedXml = new SignedXml(document); signedXml.LoadXml((XmlElement)document.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl)[0]!); Console.WriteLine(signedXml.CheckSignature()); ``` ### Expected behavior The signature validation is successful. ### Actual behavior ``` Unhandled exception. System.Security.Cryptography.CryptographicException: Unknown transform has been encountered. at System.Security.Cryptography.Xml.Reference.LoadXml(XmlElement value) at System.Security.Cryptography.Xml.SignedInfo.LoadXml(XmlElement value) at System.Security.Cryptography.Xml.Signature.LoadXml(XmlElement value) at System.Security.Cryptography.Xml.SignedXml.LoadXml(XmlElement value) ``` ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration _No response_ ### Other information I have a signature produced by a Java application that uses a different XPath transform. This signature also cannot be validated. ```xml not(ancestor-or-self::ds:Signature) ``` Adding `http://www.w3.org/TR/1999/REC-xpath-19991116` algorithm in `SafeCanonicalizationMethods` property allows to bypass [IsSafeTransform](https://github.com/dotnet/runtime/blob/210a7a9feec64b7fac5147656cddb199ec90cf75/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs#L697) check but then throws `XPathException`, maybe related to this #21451 issue. ```csharp signedXml.SafeCanonicalizationMethods.Add("http://www.w3.org/TR/1999/REC-xpath-19991116"); ``` ``` Unhandled exception. System.Xml.XPath.XPathException: Namespace prefix 'ds' is not defined. at MS.Internal.Xml.XPath.CompiledXpathExpr.UndefinedXsltContext.LookupNamespace(String prefix) at MS.Internal.Xml.XPath.BaseAxisQuery.SetXsltContext(XsltContext context) at MS.Internal.Xml.XPath.CompiledXpathExpr.SetContext(IXmlNamespaceResolver nsResolver) at System.Security.Cryptography.Xml.XmlDsigXPathTransform.GetOutput() at System.Security.Cryptography.Xml.TransformChain.TransformToOctetStream(Object inputObject, Type inputType, XmlResolver resolver, String baseUri) at System.Security.Cryptography.Xml.TransformChain.TransformToOctetStream(XmlDocument document, XmlResolver resolver, String baseUri) at System.Security.Cryptography.Xml.Reference.CalculateHashValue(XmlDocument document, CanonicalXmlNodeList refList) at System.Security.Cryptography.Xml.SignedXml.CheckDigestedReferences() at System.Security.Cryptography.Xml.SignedXml.CheckSignature(AsymmetricAlgorithm key) at System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey(AsymmetricAlgorithm& signingKey) at System.Security.Cryptography.Xml.SignedXml.CheckSignature() ```
Author: petarpetrovt
Assignees: -
Labels: `area-System.Security`, `untriaged`
Milestone: -
jeffhandley commented 1 year ago

Thanks for reporting this, @petarpetrovt. We won't be able to investigate this further during .NET 8, so I'm moving this to Future. I'm going to label this as https://github.com/dotnet/runtime/labels/help%20wanted, inviting help on further investigation to be certain we know how to fix it.

ankyrawat1 commented 4 months ago

I'm facing the same issue with the netstandard version of the "System.Security.Cryptography.Xml" dll.....with the net framework version of this dll , it works perfectly fine

This exception was originally thrown at this call stack: System.Security.Cryptography.Xml.Reference.LoadXml(System.Xml.XmlElement) in Reference.cs System.Security.Cryptography.Xml.SignedInfo.LoadXml(System.Xml.XmlElement) in SignedInfo.cs System.Security.Cryptography.Xml.Signature.LoadXml(System.Xml.XmlElement) in Signature.cs System.Security.Cryptography.Xml.SignedXml.LoadXml(System.Xml.XmlElement) in SignedXml.cs