dotnet/wpf · error · XmlException

SR.UnsupportedTransformAlgorithm

Error message

SR.UnsupportedTransformAlgorithm

What it means

GenerateDigestValue converts each ds:Transform name in a signature reference into a transform object; if StringToTransform returns null the algorithm name is not supported by the OPC/WPF XML digital signature implementation and an XmlException is thrown, marking the signature invalid.

Solutions

  1. Re-sign the package using the supported transforms only (e.g. the OPC-required canonicalization transforms) via PackageDigitalSignatureManager.Sign.
  2. Inspect the signature XML and remove/replace unsupported ds:Transform elements.
  3. Verify signatures with a more complete XML-DSig implementation (System.Security.Cryptography.Xml directly, or a third-party library) instead of WPF's package signature verification.
  4. If you control the signer, restrict transforms to the OPC-supported set.

Example fix

// before: signer applies an unsupported transform
ref.AddTransform(new XmlDsigXPathTransform(xpath));
// after: keep only supported transforms
ref.AddTransform(new XmlDsigC14NTransform());
Defensive patterns

Strategy: validation

Validate before calling

var doc = XDocument.Load(signaturePartXml);
var supported = new[] { "http://www.w3.org/TR/2001/REC-xml-c14n-20010315", "http://www.w3.org/2001/10/xml-exc-c14n#" };
bool transformsOk = doc.Descendants(ds + "Transform")
    .All(t => supported.Contains((string)t.Attribute("Algorithm")));

Try / catch

try { status = dsm.VerifySignatures(); }
catch (XmlException ex) when (ex.Message.Contains("transform")) { /* signature uses unsupported transform - treat as invalid */ }

Prevention

When it happens

Trigger: Verifying an OPC digital signature whose ds:Reference contains a ds:TransformAlgorithm attribute naming an algorithm outside those supported (e.g. XSLT, XPath, or newer canonicalization transforms not in the supported set).

Common situations: Signatures produced by other stacks (XAdES toolkits, Java/.NET Core signing tools, custom signing services) that apply transforms WPF's XmlDigitalSignatureProcessor doesn't recognize; verifying documents signed outside the OPC signing APIs.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/b91bc0f91e7f3225. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/XmlDigitalSignatureProcessor.cs:458

            {
                transformStreams = new List<Stream>(transforms.Count);
                transformStreams.Add(transformStream);
                foreach (String transformName in transforms)
                {
                    // ignore empty strings at this point (as well as Relationship Transforms) - these are legal
                    if ((transformName.Length == 0)
                        || (string.Equals(transformName, XTable.Get(XTable.ID.RelationshipsTransformName), StringComparison.Ordinal)))
                    {
                        continue;
                    }

                    // convert the transform names into objects (if defined)
                    Transform transform = StringToTransform(transformName);

                    if (transform == null)
                    {
                        // throw XmlException so the outer loop knows the signature is invalid
                        throw new XmlException(SR.UnsupportedTransformAlgorithm);
                    }

                    transformStream = TransformXml(transform, transformStream);
                    transformStreams.Add(transformStream);
                }
            }

            // hash it and encode to Base64
            String hashValueString = System.Convert.ToBase64String(HashStream(hashAlgorithm, transformStream));

            // dispose of any generated streams
            if (transformStreams != null)
            {
                foreach (Stream stream in transformStreams)
                    stream.Close();
            }

            return hashValueString;

View on GitHub (pinned to 81131a70a4)