Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET 4.6.2 Break Changing - SignedXml.CheckSignature(X509Certificate2, bool) #341

Closed
felipepessoto opened this issue Dec 15, 2016 · 28 comments

Comments

@felipepessoto
Copy link

felipepessoto commented Dec 15, 2016

As described here: http://www.wiktorzychla.com/2016/08/signedxmlchecksignature-and-dreadful.html

SignedXml.CheckSignature in 4.6.2 doesn't work as before.

Looking the source code: https://referencesource.microsoft.com/#System.Security/system/security/cryptography/xml/signedxml.cs,b9518cc2212419a2

You can see that it ends up calling : CheckSignature(certificate.GetAnyPublicKey()) - https://referencesource.microsoft.com/#System.Security/system/security/cryptography/xml/signedxml.cs,342

GetAnyPublicKey calls X509Certificate2.GetRSAPublicKey(), which return a System.Security.Cryptography.RSACng.

Whereas that .NET 4.6.1 calls CheckSignature(certificate.PublicKey.Key) working as expected.

As a workaround I am changing my calls from:

SignedXml.CheckSignature(myCert, true)

to:

SignedXml.CheckSignature(myCert.PublicKey.Key)

Simulating what SignedXml.CheckSignature(X509Certificate2, bool) does in 4.6.1

@lukaszdechovan
Copy link

After updating .NET FW to 4.6.2 we experienced the same issue. We ended up with "CryptographicException: Object was not found" exception.

However, in our case it was a WCF service hosted inside IIS web application and changing the option "Load User Profile" to True instead of False solved the problem for us (in Advanced Settings of Application Pool).

@hhotham
Copy link

hhotham commented Feb 14, 2017

We are currently getting this:
System.Security.Cryptography.CryptographicException: An internal error occurred. at System.Security.Cryptography.NCryptNative.OpenStorageProvider(String providerName) at System.Security.Cryptography.CngKey.Create(CngAlgorithm algorithm, String keyName, CngKeyCreationParameters creationParameters) at System.Security.Cryptography.RSACng.get_Key() at System.Security.Cryptography.RSACng.Encrypt(Byte[] data, RSAEncryptionPadding padding) at System.Security.Cryptography.RSAPKCS1KeyExchangeFormatter.CreateKeyExchange(Byte[] rgbData) at System.Security.Cryptography.CngLightup.DetectRsaCngSupport() at System.Lazy1.CreateValue() at System.Lazy1.LazyInitValue() at System.Security.Cryptography.CngLightup.GetRSAPublicKey(X509Certificate2 cert) at System.Security.Cryptography.X509Certificates.X509CertificateExtensions.GetAnyPublicKey(X509Certificate2 c) at System.Security.Cryptography.Xml.SignedXml.GetPublicKey() at System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey(AsymmetricAlgorithm& signingKey) at System.Security.Cryptography.Xml.SignedXml.CheckSignature()

@k31tha
Copy link

k31tha commented Feb 27, 2017

@hhotham did you solve the issue at your end
I am also experiencing the following
System.Security.Cryptography.CryptographicException: Object was not found. at System.Security.Cryptography.NCryptNative.CreatePersistedKey(SafeNCryptProviderHandle provider, String algorithm, String name, CngKeyCreationOptions options) at System.Security.Cryptography.CngKey.Create(CngAlgorithm algorithm, String keyName, CngKeyCreationParameters creationParameters) at System.Security.Cryptography.RSACng.get_Key() at System.Security.Cryptography.RSACng.Encrypt(Byte[] data, RSAEncryptionPadding padding) at System.Security.Cryptography.RSAPKCS1KeyExchangeFormatter.CreateKeyExchange(Byte[] rgbData) at System.Security.Cryptography.CngLightup.DetectRsaCngSupport() at System.Lazy1.CreateValue() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Lazy1.get_Value() at System.Security.Cryptography.CngLightup.GetRSAPublicKey(X509Certificate2 cert) at System.Security.Cryptography.X509Certificates.X509CertificateExtensions.GetAnyPublicKey(X509Certificate2 c) at System.Security.Cryptography.Xml.SignedXml.GetPublicKey() at System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey(AsymmetricAlgorithm& signingKey)

@richlander
Copy link
Member

Looking into this ...

/cc @terrajobst

@terrajobst
Copy link
Member

@Petermarcu, are you aware of any rough spots in that area?

@Petermarcu
Copy link
Member

@krwq @danmosemsft

@krwq
Copy link
Member

krwq commented Mar 11, 2017

cc: @bartonjs @morganbr - this seems to be desktop thing - was it something which happened during the security related fixes? Is this some known failure?

@bartonjs
Copy link
Member

A fix is already being prepared for future .NET Framework releases and servicing updates to .NET 4.6.2.

Two workarounds are known at this time: 1) Upgrading the OS to Windows Server 2012R2 or newer, 2) loading the user profile.

@felipepessoto
Copy link
Author

felipepessoto commented Mar 12, 2017

@bartonjs the fix is only for CryptographicException: Object was not found? Or also fixes the different behavior when validating signature?

@bartonjs
Copy link
Member

@fujiy It will avoid the path where CngLightup ends up calling CngKey.Create. If you're having a problem that isn't caused by that, we'd need a new bug report.

@hhotham
Copy link

hhotham commented Mar 14, 2017

We had to change the code.

In regard to workarounds, we couldn't upgrade to 2012R2, and load user profile was already set.

We extracted the certificate from the signedXml and then called signedXml.CheckSignature(cert.PublicKey.Key) with the cert we had extracted from signedXml

@zchpit
Copy link

zchpit commented Jun 21, 2017

After upgrade to .net 4.6.2 I have problem with signedXml.CheckSignature(); with CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

It works on my machine but don't work on test serwer. Error:

System.Security.Cryptography.CryptographicException SignatureDescription could not be created for the signature algorithm supplied.
at System.Security.Cryptography.Xml.SignedXml.CheckSignedInfo(AsymmetricAlgorithm key)
at System.Security.Cryptography.Xml.SignedXml.CheckSignature(AsymmetricAlgorithm key)
at System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey(AsymmetricAlgorithm& signingKey)
at ePR.Biz.Security.Signature.Veryfier.EprDsigSimpleVerifier.VerifyXml(XmlDocument doc, X509Certificate2& cert)
at ePR.Biz.Security.Signature.Veryfier.EprDsigSimpleVerifier.Verify(FileContentInfo fci, X509Certificate2& cert, String& stringSignature)
at ePR.Biz.Security.Signature.SignatureManager.ValidateSignatureCore(ISignatureVeryfier veryfier, FileContentInfo fci)
at ePR.Biz.Security.Signature.SignatureManager.ValidateSignature(XmlDocument doc)

P.S. In my comuper I work as administator and run as Console App., in test serwer there is custom profile created and run as a Windows Service

@bartonjs
Copy link
Member

@zchpit That exception means that the signature algorithm in the document didn't map to a known SignatureDescription. Check that the signature method is what you expect. Note that you shouldn't need the AddAlgorithm call anymore, but also that it shouldn't break things.

@zchpit
Copy link

zchpit commented Jun 22, 2017

@bartonjs what dll name I should add to solution that this method recognise SignatureDescription?

Or how to do it manualy?

P.S.
xml.SignedInfo.SignatureMethod = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

@Petermarcu
Copy link
Member

@bartonjs @zchpit is there any more follow up needed here?

@richlander
Copy link
Member

@bartonjs I read that @zchpit has one more guidance question. Can you help?

@christru
Copy link

Same issue, can't upgrade to 2012 and load user profile is not working.. Any other work arounds?

@bartonjs
Copy link
Member

@christru What is the error that you're getting? A couple of different exceptions have been discussed on this issue.

@bartonjs
Copy link
Member

@zchpit Sorry, I missed... a lot... of notifications from this issue in November. Apparently.

On systems with 4.6.2 installed the RSA+SHA256 signature method is available and works fine. If you don't have 4.6.2 installed you need to make a handler for it and register it with CryptoConfig. https://social.msdn.microsoft.com/Forums/vstudio/en-US/6438011b-92fb-4123-a22f-ad071efddf85/xml-digital-signature-with-sha256-algorithm?forum=netfxbcl#7bf8d91a-6bf9-4ee7-90c6-b9e0f3a48706 looks like a good example of this.

@christru
Copy link

christru commented Mar 22, 2018

@bartonjs the limited trace I have -
System.Security.Cryptography.NCryptNative.OpenStorage
Provider(String providerName)\r\n at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, Stri
ng curveName, CngKeyBlobFormat format, CngProvider provider)\r\n at System.Security.Cryptography.X50
9Certificates.RSACertificateExtensions.GetRSAPublicKey(X509Certificate2 certificate)\r\n at System.S
ecurity.Cryptography.X509Certificates.X509CertificateExtensions.GetAnyPublicKey(X509Certificate2 c)\r
n at System.Security.Cryptography.Xml.SignedXml.CheckSignature(X509Certificate2 certificate, Boolean
verifySignatureOnly)

Happens when calling: SignedXml.CheckSignature(myCert, true)

thanks

@bartonjs
Copy link
Member

@christru Are you on a 4.6.2 preview build? The callstack there doesn't look right for either 4.6.1 or 4.6.2+. If so, the answer is probably to upgrade to full 4.6.2 (and then accept the updates which fixed this problem)

@christru
Copy link

@bartonjs registry states
image

Excuse the \r\n enabled additional debugging error is being returned via json result.

Yes - it looks slightly different in this production environment then we have recreated in ours.
Do you know why "Load User Profile" would work as expected in one enviroment and not the other. 2k8r2? 4.6.2

@bartonjs
Copy link
Member

Do you know why "Load User Profile" would work as expected in one enviroment and not the other. 2k8r2?

No, the difference is in the Windows CNG library underneath .NET, I don't fully understand the difference. Our main fix for the problem was to detect when CNG wasn't working and fall back to the older crypto library (CAPI).

If you were calling CheckSignature(cert, true) you can force CAPI to be used by changing your call to CheckSignature(cert.PublicKey.Key). The only failure that I know of on 2008R2 was solved by load user profile. If you can make a repro you can share we'd be happy to investigate, but I've not been able to get this failure under a debugger.

@christru
Copy link

@bartonjs Awesome, thank you for all your insight and quick response Jeremy!
I need to take this back to the team and decide on the next steps. Thanks again!

@felipepessoto
Copy link
Author

The issue I first mentioned didn't throw Exceptions, and I didn't try enabling User Load Profile.

The problem was that the same SignedXml returns true in 4.6.1 and returns false in 4.6.2 when calling:

SignedXml.CheckSignature(myCert, true)

@bartonjs
Copy link
Member

@fujiy The page you liked to for "as described here" is talking about an exception caused by not loading the user profile.

I don't know of situations where it would switch from true to false (and back to true by using cert.PublicKey.Key). I'd be curious to see a repro for that, too. If you don't have one you can share, you can try seeing where it went wrong via the SignedXml logging (https://stackoverflow.com/a/41430472/6535399 being the first example I saw of that)

@felipepessoto
Copy link
Author

I don't have any repro anymore :/

@kalaskarsanket
Copy link
Contributor

This issue has not got any input for long time and we have changed were issues are tracked. If this is still an issue kindly raise a new issue in the appropriate repo as mentioned in dotnet/1275

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests