dotnet / runtime

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

SignedXml detailed failure feedback inaccessible #23358

Open CornedBee opened 7 years ago

CornedBee commented 7 years ago

I've got a simple test case where I sign a bit of XML and then try to verify its signature. Verification of the signature fails - SignedXml.CheckSignature() returns false.

The problem is that I cannot find out why it fails. Does it fail while getting a public key, looking up a certificate, validating the certificate, or validating the signature? Did I do something wrong during signing and there's now necessary information missing? I don't know - all I get is a simple false return value.

Looking at the source, SignedXml does extensive logging via System.Diagnostics.TraceSource, but it hides the actual TraceSource as a private static member of an internal logging helper class (SignedXmlDebugLog), so I can't modify the source. In the full framework, I could use an app.config file to configure the TraceSource externally, but as far as I can tell, this isn't possible in Core. The TraceSource that the debug log uses is initialized to default values and never changes.

There seems to be no way to get detailed feedback from this (complex and brittle) validation process. I think such feedback is needed.

Sebazzz commented 3 years ago

Agreed. As a temporary workaround you can use:

TraceSource source = (TraceSource) Assembly.Load("System.Security.Cryptography.Xml")
                                                     .GetType("System.Security.Cryptography.Xml.SignedXmlDebugLog")
                                                     !.GetField("s_traceSource", BindingFlags.Static | BindingFlags.NonPublic)
                                                     !.GetValue(null);

source!.Listeners.Add(new TextWriterTraceListener(TestContext.Out));
 source.Switch.Level = SourceLevels.Verbose;

You might not want to use this in production code, but for temporary troubleshooting this works well (in an integration test, for instance).

da9l commented 2 years ago

The workaround still works in .NET 6. For completeness, here is a f# version: (Obviously not for production use either)


let traceSource = 
    Assembly.Load("System.Security.Cryptography.Xml")
        .GetType("System.Security.Cryptography.Xml.SignedXmlDebugLog")
        .GetField("s_traceSource", (BindingFlags.Static ||| BindingFlags.NonPublic))
        .GetValue(null) :?> TraceSource
traceSource.Listeners.Add(new TextWriterTraceListener(System.Console.Out)) |> ignore
traceSource.Switch.Level <- SourceLevels.Verbose