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

CertificateFactory.CreateCertificateWithPrivateKey(newCert, OldCertificate) returns error in private key #606

Open
1 of 5 tasks
sveinfolkeson opened this issue May 6, 2024 · 7 comments · May be fixed by #607
Open
1 of 5 tasks
Assignees
Labels
bug Something isn't working GDS

Comments

@sveinfolkeson
Copy link

Type of issue

  • Bug
  • Enhancement
  • Compliance
  • Question
  • Help wanted

Current Behavior

I am using GlobalDiscoveryServer and GlobalDiscoveryClient ver 1.4.374.
When I create a Certificate for an UA Server everything seems to work well using new X509Certificate2(privateKeyPFX, string.Empty, X509KeyStorageFlags.Exportable);.
When I try to recreate the certificate using CertificateFactory.CreateCertificateWithPrivateKey(newCert, oldCertificate); the property PrivateKey reports the exception 'newCert.PrivateKey' threw an exception of type 'System.Security.Cryptography.CryptographicException'

Expected Behavior

No response

Steps To Reproduce

Using the sample software from https://github.com/OPCFoundation/UA-.NETStandard-Samples ver 1.4.374:

  1. Start Global Discovery Server
  2. Start Global Discovery Client
  3. Remove any certificates from the Certificate Store LocalMachine/UA Applications
  4. Register and create a new certificate
  5. Click on the Create Certificate button once more to recreate the Certificate.

Environment

- OS: Win11
- Environment: Visual Studio 2022
- Runtime: .NET 4.8
- Nuget Version: 1.4.374
- Component: Opc.Ua
- Server: UA Global Discovery Server (https://github.com/OPCFoundation/UA-.NETStandard-Samples)
- Client: UA Global Discovery Agent (https://github.com/OPCFoundation/UA-.NETStandard-Samples)

Anything else?

No response

@romanett romanett transferred this issue from OPCFoundation/UA-.NETStandard May 6, 2024
@romanett
Copy link
Contributor

romanett commented May 6, 2024

Please try again with the changes from #598 this may fix the issue, if not please inform us

@romanett romanett self-assigned this May 6, 2024
@sveinfolkeson
Copy link
Author

sveinfolkeson commented May 6, 2024 via email

@romanett
Copy link
Contributor

romanett commented May 7, 2024

@sveinfolkeson I can reproduce the issue when creating a certificate into a local X509 store. The first time it works the second time an Exception is thrown, when it tries to reuse the private Key.

Issue is the following:
-> The key is marked as "non exportable"

This happens because the X509 Store implementation creates a copy of the Cert with Flag X509KeyStorageFlags.PersistKeySet

https://github.com/OPCFoundation/UA-.NETStandard/blob/663ed10285153955bc009e464fb35f162512aaa7/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore.cs#L146

as a workaround just use a directory Certificate store

@sveinfolkeson
Copy link
Author

sveinfolkeson commented May 7, 2024 via email

@romanett
Copy link
Contributor

romanett commented May 8, 2024

@sveinfolkeson the certificate is created correctly with private key, but the private key is marked as "non exportable" however to get the old private key into the new cert created by the certificate signing request an export is needed, this fails however with X509stores in the current implementation. A workaround would be to use a diretory certificate store

at System.Security.Cryptography.NCryptNative.ExportKey(SafeNCryptKeyHandle key, String format)
at System.Security.Cryptography.CngKey.Export(CngKeyBlobFormat format)
at System.Security.Cryptography.RSACng.ExportParameters(Boolean includePrivateParameters)
at System.Security.Cryptography.X509Certificates.RSACertificateExtensions.CopyWithPrivateKey(X509Certificate2 certificate, RSA privateKey)
at Opc.Ua.Gds.Client.ApplicationCertificateControl.<CertificateRequestTimer_Tick>d__11.MoveNext() in C:\Users\roman\source\repos\romanett\UA-.NETStandard-Samples\Samples\GDS\Client\Controls\ApplicationCertificateControl.cs:line 333

@sveinfolkeson
Copy link
Author

sveinfolkeson commented May 8, 2024 via email

@sveinfolkeson
Copy link
Author

#607 Fixes the problem, but I think it will be good practice to delete the old certificate before a new one is created to avoid ending up with more than one certificate in the store.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working GDS
Projects
None yet
2 participants