diff --git a/.azurepipelines/ci.yml b/.azurepipelines/ci.yml index d6dccac88..7229e8aac 100644 --- a/.azurepipelines/ci.yml +++ b/.azurepipelines/ci.yml @@ -33,6 +33,11 @@ jobs: - task: NuGetToolInstaller@1 inputs: versionSpec: '>=5.8.x' + - task: UseDotNet@2 + displayName: 'Install .NET 9.0' + inputs: + packageType: 'sdk' + version: '9.0.x' - task: PowerShell@2 displayName: Versioning inputs: diff --git a/.azurepipelines/preview.yml b/.azurepipelines/preview.yml index ac06f4d70..cb31bbb9b 100644 --- a/.azurepipelines/preview.yml +++ b/.azurepipelines/preview.yml @@ -34,10 +34,10 @@ jobs: value: '.azurepipelines/signlist${{parameters.config}}.txt' steps: - task: UseDotNet@2 - displayName: 'Install .NET 8.0' + displayName: 'Install .NET 9.0' inputs: packageType: 'sdk' - version: '8.0.x' + version: '9.0.x' includePreviewVersions: false - task: DownloadSecureFile@1 name: strongnamefile diff --git a/.azurepipelines/signlistDebug.txt b/.azurepipelines/signlistDebug.txt index 077e6c470..9e75cc3a4 100644 --- a/.azurepipelines/signlistDebug.txt +++ b/.azurepipelines/signlistDebug.txt @@ -4,56 +4,66 @@ Stack\Opc.Ua.Core\bin\Debug\net472\Opc.Ua.Core.dll Stack\Opc.Ua.Core\bin\Debug\net48\Opc.Ua.Core.dll Stack\Opc.Ua.Core\bin\Debug\net6.0\Opc.Ua.Core.dll Stack\Opc.Ua.Core\bin\Debug\net8.0\Opc.Ua.Core.dll +Stack\Opc.Ua.Core\bin\Debug\net9.0\Opc.Ua.Core.dll Stack\Opc.Ua.Bindings.Https\bin\Debug\netstandard2.0\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Debug\netstandard2.1\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Debug\net472\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Debug\net48\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Debug\net6.0\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Debug\net8.0\Opc.Ua.Bindings.Https.dll +Stack\Opc.Ua.Bindings.Https\bin\Debug\net9.0\Opc.Ua.Bindings.Https.dll Libraries\Opc.Ua.Server\bin\Debug\netstandard2.0\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Debug\netstandard2.1\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Debug\net472\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Debug\net48\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Debug\net6.0\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Debug\net8.0\Opc.Ua.Server.dll +Libraries\Opc.Ua.Server\bin\Debug\net9.0\Opc.Ua.Server.dll Libraries\Opc.Ua.Client\bin\Debug\netstandard2.0\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Debug\netstandard2.1\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Debug\net472\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Debug\net48\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Debug\net6.0\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Debug\net8.0\Opc.Ua.Client.dll +Libraries\Opc.Ua.Client\bin\Debug\net9.0\Opc.Ua.Client.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\netstandard2.1\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net462\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net472\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net48\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net6.0\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net8.0\Opc.Ua.Client.ComplexTypes.dll +Libraries\Opc.Ua.Client.ComplexTypes\bin\Debug\net9.0\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Configuration\bin\Debug\netstandard2.0\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Debug\netstandard2.1\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Debug\net472\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Debug\net48\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Debug\net6.0\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Debug\net8.0\Opc.Ua.Configuration.dll +Libraries\Opc.Ua.Configuration\bin\Debug\net9.0\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\netstandard2.0\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\netstandard2.1\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net472\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net48\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net6.0\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net8.0\Opc.Ua.Gds.Client.Common.dll +Libraries\Opc.Ua.Gds.Client.Common\bin\Debug\net9.0\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\netstandard2.0\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\netstandard2.1\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net472\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net48\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net6.0\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net8.0\Opc.Ua.Gds.Server.Common.dll +Libraries\Opc.Ua.Gds.Server.Common\bin\Debug\net9.0\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Security.Certificates\bin\Debug\netstandard2.0\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Debug\netstandard2.1\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Debug\net472\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Debug\net48\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Debug\net6.0\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Debug\net8.0\Opc.Ua.Security.Certificates.dll +Libraries\Opc.Ua.Security.Certificates\bin\Debug\net9.0\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.PubSub\bin\Debug\netstandard2.1\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Debug\net472\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Debug\net48\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Debug\net6.0\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Debug\net8.0\Opc.Ua.PubSub.dll +Libraries\Opc.Ua.PubSub\bin\Debug\net9.0\Opc.Ua.PubSub.dll diff --git a/.azurepipelines/signlistRelease.txt b/.azurepipelines/signlistRelease.txt index c42668f93..2766d2698 100644 --- a/.azurepipelines/signlistRelease.txt +++ b/.azurepipelines/signlistRelease.txt @@ -4,56 +4,66 @@ Stack\Opc.Ua.Core\bin\Release\net472\Opc.Ua.Core.dll Stack\Opc.Ua.Core\bin\Release\net48\Opc.Ua.Core.dll Stack\Opc.Ua.Core\bin\Release\net6.0\Opc.Ua.Core.dll Stack\Opc.Ua.Core\bin\Release\net8.0\Opc.Ua.Core.dll +Stack\Opc.Ua.Core\bin\Release\net9.0\Opc.Ua.Core.dll Stack\Opc.Ua.Bindings.Https\bin\Release\netstandard2.0\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Release\netstandard2.1\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Release\net472\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Release\net48\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Release\net6.0\Opc.Ua.Bindings.Https.dll Stack\Opc.Ua.Bindings.Https\bin\Release\net8.0\Opc.Ua.Bindings.Https.dll +Stack\Opc.Ua.Bindings.Https\bin\Release\net9.0\Opc.Ua.Bindings.Https.dll Libraries\Opc.Ua.Server\bin\Release\netstandard2.0\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Release\netstandard2.1\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Release\net472\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Release\net48\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Release\net6.0\Opc.Ua.Server.dll Libraries\Opc.Ua.Server\bin\Release\net8.0\Opc.Ua.Server.dll +Libraries\Opc.Ua.Server\bin\Release\net9.0\Opc.Ua.Server.dll Libraries\Opc.Ua.Client\bin\Release\netstandard2.0\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Release\netstandard2.1\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Release\net472\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Release\net48\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Release\net6.0\Opc.Ua.Client.dll Libraries\Opc.Ua.Client\bin\Release\net8.0\Opc.Ua.Client.dll +Libraries\Opc.Ua.Client\bin\Release\net9.0\Opc.Ua.Client.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\netstandard2.1\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net462\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net472\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net48\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net6.0\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net8.0\Opc.Ua.Client.ComplexTypes.dll +Libraries\Opc.Ua.Client.ComplexTypes\bin\Release\net9.0\Opc.Ua.Client.ComplexTypes.dll Libraries\Opc.Ua.Configuration\bin\Release\netstandard2.0\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Release\netstandard2.1\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Release\net472\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Release\net48\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Release\net6.0\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Configuration\bin\Release\net8.0\Opc.Ua.Configuration.dll +Libraries\Opc.Ua.Configuration\bin\Release\net9.0\Opc.Ua.Configuration.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Release\netstandard2.0\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Release\netstandard2.1\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net472\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net48\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net6.0\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net8.0\Opc.Ua.Gds.Client.Common.dll +Libraries\Opc.Ua.Gds.Client.Common\bin\Release\net9.0\Opc.Ua.Gds.Client.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Release\netstandard2.0\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Release\netstandard2.1\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net472\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net48\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net6.0\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net8.0\Opc.Ua.Gds.Server.Common.dll +Libraries\Opc.Ua.Gds.Server.Common\bin\Release\net9.0\Opc.Ua.Gds.Server.Common.dll Libraries\Opc.Ua.Security.Certificates\bin\Release\netstandard2.0\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Release\netstandard2.1\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Release\net472\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Release\net48\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Release\net6.0\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.Security.Certificates\bin\Release\net8.0\Opc.Ua.Security.Certificates.dll +Libraries\Opc.Ua.Security.Certificates\bin\Release\net9.0\Opc.Ua.Security.Certificates.dll Libraries\Opc.Ua.PubSub\bin\Release\netstandard2.1\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Release\net472\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Release\net48\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Release\net6.0\Opc.Ua.PubSub.dll Libraries\Opc.Ua.PubSub\bin\Release\net8.0\Opc.Ua.PubSub.dll +Libraries\Opc.Ua.PubSub\bin\Release\net9.0\Opc.Ua.PubSub.dll diff --git a/.azurepipelines/test.yml b/.azurepipelines/test.yml index 12f7449ad..7d926e294 100644 --- a/.azurepipelines/test.yml +++ b/.azurepipelines/test.yml @@ -47,10 +47,10 @@ jobs: packageType: 'sdk' version: '6.0.x' - task: UseDotNet@2 - displayName: 'Install .NET 8.0' + displayName: 'Install .NET 9.0' inputs: packageType: 'sdk' - version: '8.0.x' + version: '9.0.x' - task: NuGetToolInstaller@1 inputs: versionSpec: '>=5.8.x' diff --git a/.azurepipelines/testcc.yml b/.azurepipelines/testcc.yml index 4f2fdb8ad..67d7861e6 100644 --- a/.azurepipelines/testcc.yml +++ b/.azurepipelines/testcc.yml @@ -30,10 +30,10 @@ jobs: packageType: 'sdk' version: '6.0.x' - task: UseDotNet@2 - displayName: 'Install .NET 8.0' + displayName: 'Install .NET 9.0' inputs: packageType: 'sdk' - version: '8.0.x' + version: '9.0.x' - task: NuGetToolInstaller@1 inputs: versionSpec: '>=5.8.x' diff --git a/.github/workflows/buildandtest.yml b/.github/workflows/buildandtest.yml index 00533e258..001359d2b 100644 --- a/.github/workflows/buildandtest.yml +++ b/.github/workflows/buildandtest.yml @@ -1,4 +1,4 @@ -name: Build and Test .NET 8.0 +name: Build and Test .NET 9.0 on: push: @@ -22,10 +22,10 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] csproj: [Security.Certificates, Core, Server, Client, Client.ComplexTypes, PubSub, Configuration, Gds] include: - - framework: 'net8.0' - dotnet-version: '8.0.x' + - framework: 'net9.0' + dotnet-version: '9.0.x' configuration: 'Release' - customtesttarget: net8.0 + customtesttarget: net9.0 env: OS: ${{ matrix.os }} diff --git a/Applications/ConsoleReferenceClient/ConsoleReferenceClient.csproj b/Applications/ConsoleReferenceClient/ConsoleReferenceClient.csproj index bdfd44f97..04bf1da45 100644 --- a/Applications/ConsoleReferenceClient/ConsoleReferenceClient.csproj +++ b/Applications/ConsoleReferenceClient/ConsoleReferenceClient.csproj @@ -20,9 +20,9 @@ - - - + + + diff --git a/Applications/ConsoleReferenceServer/ConsoleReferenceServer.csproj b/Applications/ConsoleReferenceServer/ConsoleReferenceServer.csproj index 0fb89a57e..0c9ea93ce 100644 --- a/Applications/ConsoleReferenceServer/ConsoleReferenceServer.csproj +++ b/Applications/ConsoleReferenceServer/ConsoleReferenceServer.csproj @@ -29,9 +29,9 @@ - - - + + + diff --git a/Libraries/Opc.Ua.Client/Session/Session.cs b/Libraries/Opc.Ua.Client/Session/Session.cs index 3de3e6573..66fe2fd55 100644 --- a/Libraries/Opc.Ua.Client/Session/Session.cs +++ b/Libraries/Opc.Ua.Client/Session/Session.cs @@ -1075,7 +1075,7 @@ public static async Task CreateChannelAsync( endpoint.Description.ServerCertificate.Length > 0) { configuration.CertificateValidator?.ValidateDomains( - new X509Certificate2(endpoint.Description.ServerCertificate), + X509CertificateLoader.LoadCertificate(endpoint.Description.ServerCertificate), endpoint); checkDomain = false; } @@ -1439,7 +1439,7 @@ public bool ApplySessionConfiguration(SessionConfiguration sessionConfiguration) byte[] serverCertificate = m_endpoint.Description?.ServerCertificate; m_sessionName = sessionConfiguration.SessionName; - m_serverCertificate = serverCertificate != null ? new X509Certificate2(serverCertificate) : null; + m_serverCertificate = serverCertificate != null ? X509CertificateLoader.LoadCertificate(serverCertificate) : null; m_identity = sessionConfiguration.Identity; m_checkDomain = sessionConfiguration.CheckDomain; m_serverNonce = sessionConfiguration.ServerNonce; diff --git a/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs b/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs index 1734790b1..6ee1b5497 100644 --- a/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs +++ b/Libraries/Opc.Ua.Configuration/ApplicationInstance.cs @@ -631,7 +631,9 @@ private async Task CheckApplicationInstanceCertificateAsync( { // validate certificate. configuration.CertificateValidator.CertificateValidation += certValidator.OnCertificateValidation; - await configuration.CertificateValidator.ValidateAsync(certificate.HasPrivateKey ? new X509Certificate2(certificate.RawData) : certificate, ct).ConfigureAwait(false); + await configuration.CertificateValidator.ValidateAsync( + certificate.HasPrivateKey ? + X509CertificateLoader.LoadCertificate(certificate.RawData) : certificate, ct).ConfigureAwait(false); } catch (Exception ex) { @@ -995,7 +997,8 @@ private static async Task AddToTrustedStoreAsync(ApplicationConfiguration config } // add new certificate. - X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); + X509Certificate2 publicKey = X509CertificateLoader.LoadCertificate(certificate.RawData); + await store.Add(publicKey).ConfigureAwait(false); Utils.LogInfo("Added application certificate to trusted peer store."); diff --git a/Libraries/Opc.Ua.Gds.Client.Common/ServerPushConfigurationClient.cs b/Libraries/Opc.Ua.Gds.Client.Common/ServerPushConfigurationClient.cs index 40940834f..11e3d973b 100644 --- a/Libraries/Opc.Ua.Gds.Client.Common/ServerPushConfigurationClient.cs +++ b/Libraries/Opc.Ua.Gds.Client.Common/ServerPushConfigurationClient.cs @@ -721,7 +721,7 @@ public X509Certificate2Collection GetRejectedList() X509Certificate2Collection collection = new X509Certificate2Collection(); foreach (var rawCertificate in rawCertificates) { - collection.Add(new X509Certificate2(rawCertificate)); + collection.Add(X509CertificateLoader.LoadCertificate(rawCertificate)); } return collection; } diff --git a/Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs b/Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs index bd3ca1332..fb4238de9 100644 --- a/Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs +++ b/Libraries/Opc.Ua.Gds.Server.Common/ApplicationsNodeManager.cs @@ -234,7 +234,7 @@ private ICertificateGroup GetGroupForCertificate(byte[] certificate) { if (certificate != null && certificate.Length > 0) { - using (var x509 = new X509Certificate2(certificate)) + using (var x509 = X509CertificateLoader.LoadCertificate(certificate)) { foreach (var certificateGroup in m_certificateGroups.Values) { @@ -258,7 +258,7 @@ private async Task RevokeCertificateAsync(byte[] certificate) if (certificateGroup != null) { - using (X509Certificate2 x509 = new X509Certificate2(certificate)) + using (X509Certificate2 x509 = X509CertificateLoader.LoadCertificate(certificate)) { try { @@ -689,7 +689,7 @@ private ServiceResult OnCheckRevocationStatus( } } - using (var x509 = new X509Certificate2(certificate)) + using (var x509 = X509CertificateLoader.LoadCertificate(certificate)) { if (chain.Build(x509)) { @@ -1305,7 +1305,7 @@ out privateKeyPassword } else { - certificate = new X509Certificate2(signedCertificate); + certificate = X509CertificateLoader.LoadCertificate(signedCertificate); } // TODO: return chain, verify issuer chain cert is up to date, otherwise update local chain diff --git a/Libraries/Opc.Ua.Gds.Server.Common/CertificateGroup.cs b/Libraries/Opc.Ua.Gds.Server.Common/CertificateGroup.cs index 1f1b6553c..8ce0249f2 100644 --- a/Libraries/Opc.Ua.Gds.Server.Common/CertificateGroup.cs +++ b/Libraries/Opc.Ua.Gds.Server.Common/CertificateGroup.cs @@ -119,7 +119,7 @@ public virtual async Task Init() Configuration.CACertificateLifetime ); X509Certificate2 newCertificate = await CreateCACertificateAsync(SubjectName).ConfigureAwait(false); - Certificate = new X509Certificate2(newCertificate.RawData); + Certificate = X509CertificateLoader.LoadCertificate(newCertificate.RawData); Utils.LogCertificate(Utils.TraceMasks.Security, "Created CA certificate: ", Certificate); } } @@ -173,7 +173,7 @@ public virtual async Task NewKeyPairRequestAsync( { throw new ServiceResultException(StatusCodes.BadInvalidArgument, "Invalid private key format"); } - return new X509Certificate2KeyPair(new X509Certificate2(certificate.RawData), privateKeyFormat, privateKey); + return new X509Certificate2KeyPair(X509CertificateLoader.LoadCertificate(certificate.RawData), privateKeyFormat, privateKey); } } @@ -336,7 +336,7 @@ string subjectName { // save only public key - Certificate = new X509Certificate2(newCertificate.RawData); + Certificate = X509CertificateLoader.LoadCertificate(newCertificate.RawData); // initialize revocation list X509CRL crl = await RevokeCertificateAsync(AuthoritiesStore, newCertificate, null).ConfigureAwait(false); @@ -494,7 +494,7 @@ protected async Task UpdateAuthorityCertInCertificateStore(CertificateStoreIdent X509Certificate2Collection certs = await trustedOrIssuerStore.FindByThumbprint(certificate.Thumbprint).ConfigureAwait(false); if (certs.Count == 0) { - using (var x509 = new X509Certificate2(certificate.RawData)) + using (var x509 = X509CertificateLoader.LoadCertificate(certificate.RawData)) { await trustedOrIssuerStore.Add(x509).ConfigureAwait(false); } diff --git a/Libraries/Opc.Ua.Gds.Server.Common/ICertificateGroup.cs b/Libraries/Opc.Ua.Gds.Server.Common/ICertificateGroup.cs index d1eac1926..787906ad6 100644 --- a/Libraries/Opc.Ua.Gds.Server.Common/ICertificateGroup.cs +++ b/Libraries/Opc.Ua.Gds.Server.Common/ICertificateGroup.cs @@ -44,7 +44,7 @@ public X509Certificate2KeyPair(X509Certificate2 certificate, string privateKeyFo { if (certificate.HasPrivateKey) { - certificate = new X509Certificate2(certificate.RawData); + certificate = X509CertificateLoader.LoadCertificate(certificate.RawData); } Certificate = certificate; PrivateKeyFormat = privateKeyFormat; diff --git a/Libraries/Opc.Ua.PubSub/Transport/MqttClientProtocolConfiguration.cs b/Libraries/Opc.Ua.PubSub/Transport/MqttClientProtocolConfiguration.cs index a5ea6a729..ba75b7b04 100644 --- a/Libraries/Opc.Ua.PubSub/Transport/MqttClientProtocolConfiguration.cs +++ b/Libraries/Opc.Ua.PubSub/Transport/MqttClientProtocolConfiguration.cs @@ -43,8 +43,8 @@ public class MqttTlsCertificates { #region Private menbers - private X509Certificate m_caCertificate; - private X509Certificate m_clientCertificate; + private X509Certificate2 m_caCertificate; + private X509Certificate2 m_clientCertificate; #endregion Private menbers @@ -64,11 +64,11 @@ public MqttTlsCertificates(string caCertificatePath = null, if (!string.IsNullOrEmpty(CaCertificatePath)) { - m_caCertificate = X509Certificate.CreateFromCertFile(CaCertificatePath); + m_caCertificate = X509CertificateLoader.LoadCertificateFromFile(CaCertificatePath); } if (!string.IsNullOrEmpty(clientCertificatePath)) { - m_clientCertificate = new X509Certificate2(clientCertificatePath, ClientCertificatePassword); + m_clientCertificate = X509CertificateLoader.LoadPkcs12FromFile(clientCertificatePath, ClientCertificatePassword); } KeyValuePairs = new KeyValuePairCollection(); @@ -105,11 +105,11 @@ public MqttTlsCertificates(KeyValuePairCollection keyValuePairs) if (!string.IsNullOrEmpty(CaCertificatePath)) { - m_caCertificate = X509Certificate.CreateFromCertFile(CaCertificatePath); + m_caCertificate = X509CertificateLoader.LoadCertificateFromFile(CaCertificatePath); } if (!string.IsNullOrEmpty(ClientCertificatePath)) { - m_clientCertificate = new X509Certificate2(ClientCertificatePath, ClientCertificatePassword); + m_clientCertificate = X509CertificateLoader.LoadPkcs12FromFile(ClientCertificatePath, ClientCertificatePassword); } } diff --git a/Libraries/Opc.Ua.PubSub/Transport/MqttPubSubConnection.cs b/Libraries/Opc.Ua.PubSub/Transport/MqttPubSubConnection.cs index 937c751dc..63b2e2763 100644 --- a/Libraries/Opc.Ua.PubSub/Transport/MqttPubSubConnection.cs +++ b/Libraries/Opc.Ua.PubSub/Transport/MqttPubSubConnection.cs @@ -737,9 +737,9 @@ private MqttClientOptions GetMqttClientOptions() var x509Certificate2s = new List(); if (mqttTlsOptions?.Certificates != null) { - foreach (X509Certificate x509cert in mqttTlsOptions?.Certificates.X509Certificates) + foreach (X509Certificate2 x509cert in mqttTlsOptions?.Certificates.X509Certificates) { - x509Certificate2s.Add(new X509Certificate2(x509cert.Handle)); + x509Certificate2s.Add(X509CertificateLoader.LoadCertificate(x509cert.RawData)); } } @@ -838,7 +838,7 @@ private static CertificateValidator CreateCertificateValidator(MqttTlsOptions mq /// The context of the validation private bool ValidateBrokerCertificate(MqttClientCertificateValidationEventArgs context) { - var brokerCertificate = new X509Certificate2(context.Certificate.GetRawCertData()); + var brokerCertificate = X509CertificateLoader.LoadCertificate(context.Certificate.GetRawCertData()); try { diff --git a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509CertificateLoader.cs b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509CertificateLoader.cs new file mode 100644 index 000000000..84c163ca3 --- /dev/null +++ b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509CertificateLoader.cs @@ -0,0 +1,91 @@ +/* ======================================================================== + * Copyright (c) 2005-2024 The OPC Foundation, Inc. All rights reserved. + * + * OPC Foundation MIT License 1.00 + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * The complete license agreement can be found here: + * http://opcfoundation.org/License/MIT/1.00/ + * ======================================================================*/ + +#if !NET9_0_OR_GREATER + +using System; +using System.Security.Cryptography.X509Certificates; + +namespace System.Security.Cryptography.X509Certificates +{ + /// + /// A helper to support the .NET 9 certificate loader primitives on older .NET versions. + /// + public static class X509CertificateLoader + { + /// + /// Initializes a new instance of the class from certificate data. + /// + public static X509Certificate2 LoadCertificate(byte[] data) + { + return new X509Certificate2(data); + } + +#if NET6_0_OR_GREATER + /// + /// Initializes a new instance of the class from certificate data. + /// + public static X509Certificate2 LoadCertificate(ReadOnlySpan rawData) + { + return new X509Certificate2(rawData); + } +#endif + + /// + /// Initializes a new instance of the class from certificate file. + /// + public static X509Certificate2 LoadCertificateFromFile(string path) + { + return new X509Certificate2(path); + } + + /// + /// Initializes a new instance of the class from Pfx data. + /// + public static X509Certificate2 LoadPkcs12( + byte[] data, + string password, + X509KeyStorageFlags keyStorageFlags = X509KeyStorageFlags.DefaultKeySet) + { + return new X509Certificate2(data, password, keyStorageFlags); + } + + /// + /// Initializes a new instance of the class from Pfx file. + /// + public static X509Certificate2 LoadPkcs12FromFile( + string filename, + string password, + X509KeyStorageFlags keyStorageFlags = X509KeyStorageFlags.DefaultKeySet) + { + return new X509Certificate2(filename, password, keyStorageFlags); + } + } +} +#endif diff --git a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs index 03ad62b1f..19909507f 100644 --- a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs +++ b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/X509PfxUtils.cs @@ -153,10 +153,11 @@ public static X509Certificate2 CreateCertificateFromPKCS12( try { // merge first cert with private key into X509Certificate2 - certificate = new X509Certificate2( + certificate = X509CertificateLoader.LoadPkcs12( rawData, password ?? string.Empty, flag); + // can we really access the private key? if (VerifyRSAKeyPair(certificate, certificate, true)) { diff --git a/Libraries/Opc.Ua.Server/Configuration/ConfigurationNodeManager.cs b/Libraries/Opc.Ua.Server/Configuration/ConfigurationNodeManager.cs index b63675147..a41431b66 100644 --- a/Libraries/Opc.Ua.Server/Configuration/ConfigurationNodeManager.cs +++ b/Libraries/Opc.Ua.Server/Configuration/ConfigurationNodeManager.cs @@ -385,12 +385,12 @@ private ServiceResult UpdateCertificate( { foreach (byte[] issuerRawCert in issuerCertificates) { - var newIssuerCert = new X509Certificate2(issuerRawCert); + var newIssuerCert = X509CertificateLoader.LoadCertificate(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } - newCert = new X509Certificate2(certificate); + newCert = X509CertificateLoader.LoadCertificate(certificate); } catch { @@ -499,7 +499,7 @@ private ServiceResult UpdateCertificate( var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; appStore.Add(updateCertificate.CertificateWithPrivateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)).Wait(); // keep only track of cert without private key - var certOnly = new X509Certificate2(updateCertificate.CertificateWithPrivateKey.RawData); + var certOnly = X509CertificateLoader.LoadCertificate(updateCertificate.CertificateWithPrivateKey.RawData); updateCertificate.CertificateWithPrivateKey.Dispose(); updateCertificate.CertificateWithPrivateKey = certOnly; } diff --git a/Libraries/Opc.Ua.Server/Configuration/TrustList.cs b/Libraries/Opc.Ua.Server/Configuration/TrustList.cs index c33e77a21..0fae605d8 100644 --- a/Libraries/Opc.Ua.Server/Configuration/TrustList.cs +++ b/Libraries/Opc.Ua.Server/Configuration/TrustList.cs @@ -347,7 +347,7 @@ private ServiceResult CloseAndUpdate( issuerCertificates = new X509Certificate2Collection(); foreach (var cert in trustList.IssuerCertificates) { - issuerCertificates.Add(new X509Certificate2(cert)); + issuerCertificates.Add(X509CertificateLoader.LoadCertificate(cert)); } } if ((masks & TrustListMasks.IssuerCrls) != 0) @@ -363,7 +363,7 @@ private ServiceResult CloseAndUpdate( trustedCertificates = new X509Certificate2Collection(); foreach (var cert in trustList.TrustedCertificates) { - trustedCertificates.Add(new X509Certificate2(cert)); + trustedCertificates.Add(X509CertificateLoader.LoadCertificate(cert)); } } if ((masks & TrustListMasks.TrustedCrls) != 0) @@ -461,7 +461,7 @@ private ServiceResult AddCertificate( X509Certificate2 cert = null; try { - cert = new X509Certificate2(certificate); + cert = X509CertificateLoader.LoadCertificate(certificate); } catch { @@ -471,7 +471,7 @@ private ServiceResult AddCertificate( result = StatusCodes.BadCertificateInvalid; } - var storeIdentifier = isTrustedCertificate? m_trustedStore : m_issuerStore; + var storeIdentifier = isTrustedCertificate ? m_trustedStore : m_issuerStore; ICertificateStore store = storeIdentifier.OpenStore(); try { diff --git a/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj b/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj index 280460251..64ef8e948 100644 --- a/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj +++ b/Stack/Opc.Ua.Core/Opc.Ua.Core.csproj @@ -42,9 +42,10 @@ - + - + + @@ -60,8 +61,7 @@ - - + @@ -71,7 +71,7 @@ - + diff --git a/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs b/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs index 2f3acaf63..9ae545707 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/CertificateFactory.cs @@ -58,10 +58,11 @@ public static class CertificateFactory public static X509Certificate2 Create(ReadOnlyMemory encodedData, bool useCache) { #if NET6_0_OR_GREATER - var certificate = new X509Certificate2(encodedData.Span); + var certificate = X509CertificateLoader.LoadCertificate(encodedData.Span); #else - var certificate = new X509Certificate2(encodedData.ToArray()); + var certificate = X509CertificateLoader.LoadCertificate(encodedData.ToArray()); #endif + if (useCache) { return Load(certificate, false); @@ -368,7 +369,7 @@ public static X509Certificate2 CreateCertificateWithPEMPrivateKey( string password = null) { RSA rsaPrivateKey = PEMReader.ImportPrivateKeyFromPEM(pemDataBlob, password); - return new X509Certificate2(certificate.RawData).CopyWithPrivateKey(rsaPrivateKey); + return X509CertificateLoader.LoadCertificate(certificate.RawData).CopyWithPrivateKey(rsaPrivateKey); } #else /// @@ -453,18 +454,18 @@ public static X509Certificate2 CreateCertificateWithPEMPrivateKey( /// The certificate with a private key. [Obsolete("Use the new CreateCertificate methods with CertificateBuilder.")] internal static X509Certificate2 CreateCertificate( - string applicationUri, - string applicationName, - string subjectName, - IList domainNames, - ushort keySize, - DateTime startTime, - ushort lifetimeInMonths, - ushort hashSizeInBits, - bool isCA = false, - X509Certificate2 issuerCAKeyCert = null, - byte[] publicKey = null, - int pathLengthConstraint = 0) + string applicationUri, + string applicationName, + string subjectName, + IList domainNames, + ushort keySize, + DateTime startTime, + ushort lifetimeInMonths, + ushort hashSizeInBits, + bool isCA = false, + X509Certificate2 issuerCAKeyCert = null, + byte[] publicKey = null, + int pathLengthConstraint = 0) { ICertificateBuilder builder = null; if (isCA) diff --git a/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs b/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs index 4e30f5d1a..2c13adf88 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/CertificateValidator.cs @@ -510,7 +510,7 @@ public virtual async Task ValidateAsync(X509Certificate2Collection chain, Config await InternalValidateAsync(chain, endpoint, ct).ConfigureAwait(false); // add to list of validated certificates. - m_validatedCertificates[certificate.Thumbprint] = new X509Certificate2(certificate.RawData); + m_validatedCertificates[certificate.Thumbprint] = X509CertificateLoader.LoadCertificate(certificate.RawData); return; } @@ -529,7 +529,7 @@ public virtual async Task ValidateAsync(X509Certificate2Collection chain, Config try { Utils.LogCertificate(LogLevel.Warning, "Validation errors suppressed: ", certificate); - m_validatedCertificates[certificate.Thumbprint] = new X509Certificate2(certificate.RawData); + m_validatedCertificates[certificate.Thumbprint] = X509CertificateLoader.LoadCertificate(certificate.RawData); } finally { @@ -554,7 +554,7 @@ public virtual void Validate(X509Certificate2Collection chain, ConfiguredEndpoin InternalValidateAsync(chain, endpoint).GetAwaiter().GetResult(); // add to list of validated certificates. - m_validatedCertificates[certificate.Thumbprint] = new X509Certificate2(certificate.RawData); + m_validatedCertificates[certificate.Thumbprint] = X509CertificateLoader.LoadCertificate(certificate.RawData); return; } @@ -574,7 +574,7 @@ public virtual void Validate(X509Certificate2Collection chain, ConfiguredEndpoin try { Utils.LogCertificate(LogLevel.Warning, "Validation errors suppressed: ", certificate); - m_validatedCertificates[certificate.Thumbprint] = new X509Certificate2(certificate.RawData); + m_validatedCertificates[certificate.Thumbprint] = X509CertificateLoader.LoadCertificate(certificate.RawData); } finally { diff --git a/Stack/Opc.Ua.Core/Security/Certificates/DirectoryCertificateStore.cs b/Stack/Opc.Ua.Core/Security/Certificates/DirectoryCertificateStore.cs index 5d61a0d9a..d99147ed3 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/DirectoryCertificateStore.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/DirectoryCertificateStore.cs @@ -450,7 +450,7 @@ public async Task LoadPrivateKey(string thumbprint, string sub { try { - var certificate = new X509Certificate2(file.FullName); + var certificate = X509CertificateLoader.LoadCertificateFromFile(file.FullName); if (!String.IsNullOrEmpty(thumbprint)) { @@ -513,10 +513,11 @@ public async Task LoadPrivateKey(string thumbprint, string sub { try { - certificate = new X509Certificate2( + certificate = X509CertificateLoader.LoadPkcs12FromFile( privateKeyFilePfx.FullName, password, flag); + if (X509Utils.VerifyRSAKeyPair(certificate, certificate, true)) { Utils.LogInfo(Utils.TraceMasks.Security, "Imported the PFX private key for [{0}].", certificate.Thumbprint); @@ -824,7 +825,7 @@ private IDictionary Load(string thumbprint) try { var entry = new Entry { - Certificate = new X509Certificate2(file.FullName), + Certificate = X509CertificateLoader.LoadCertificateFromFile(file.FullName), CertificateFile = file, PrivateKeyFile = null, CertificateWithPrivateKey = null, diff --git a/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore/X509CertificateStore.cs b/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore/X509CertificateStore.cs index 8cb54b9aa..858c24680 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore/X509CertificateStore.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore/X509CertificateStore.cs @@ -154,7 +154,7 @@ public Task Add(X509Certificate2 certificate, string password = null) else if (certificate.HasPrivateKey && m_noPrivateKeys) { // ensure no private key is added to store - using (var publicKey = new X509Certificate2(certificate.RawData)) + using (var publicKey = X509CertificateLoader.LoadCertificate(certificate.RawData)) { store.Add(publicKey); } diff --git a/Stack/Opc.Ua.Core/Security/Certificates/X509Utils.cs b/Stack/Opc.Ua.Core/Security/Certificates/X509Utils.cs index e0698029f..6188d59d9 100644 --- a/Stack/Opc.Ua.Core/Security/Certificates/X509Utils.cs +++ b/Stack/Opc.Ua.Core/Security/Certificates/X509Utils.cs @@ -511,7 +511,7 @@ public static X509Certificate2 CreateCopyWithPrivateKey(X509Certificate2 certifi // see https://github.com/dotnet/runtime/issues/29144 string passcode = GeneratePasscode(); X509KeyStorageFlags storageFlags = persisted ? X509KeyStorageFlags.PersistKeySet : X509KeyStorageFlags.Exportable; - return new X509Certificate2(certificate.Export(X509ContentType.Pfx, passcode), passcode, storageFlags); + return X509CertificateLoader.LoadPkcs12(certificate.Export(X509ContentType.Pfx, passcode), passcode, storageFlags); } return certificate; } diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index 36463b881..1e3c060a3 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -156,7 +156,7 @@ public async Task GetEndpointsAsync() if (endpoint.ServerCertificate != null) { - using (var cert = new X509Certificate2(endpoint.ServerCertificate)) + using (var cert = X509CertificateLoader.LoadCertificate(endpoint.ServerCertificate)) { TestContext.Out.WriteLine(" [{0}]", cert.Thumbprint); } diff --git a/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs b/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs index 95f0130fe..b75631815 100644 --- a/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs +++ b/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs @@ -330,7 +330,7 @@ public async Task TestNoFileConfigAsServerX509Store() { // store public key in trusted store var rawData = applicationCertificate.Certificate.RawData; - await store.Add(new X509Certificate2(rawData)).ConfigureAwait(false); + await store.Add(X509CertificateLoader.LoadCertificate(rawData)).ConfigureAwait(false); } if (deleteAfterUse) @@ -427,7 +427,7 @@ public async Task TestInvalidAppCertDoNotRecreate(InvalidCertType certType, bool applicationCertificate.StoreType, applicationCertificate.StorePath ); - publicKey = new X509Certificate2(testCert.RawData); + publicKey = X509CertificateLoader.LoadCertificate(testCert.RawData); } using (publicKey) @@ -514,7 +514,7 @@ public async Task TestInvalidAppCertChainDoNotRecreate(InvalidCertType certType, applicationCertificate.StoreType, applicationCertificate.StorePath ); - publicKey = new X509Certificate2(testCert.RawData); + publicKey = X509CertificateLoader.LoadCertificate(testCert.RawData); } using (publicKey) @@ -715,7 +715,7 @@ private X509Certificate2Collection CreateInvalidCertChain(InvalidCertType certTy var result = new X509Certificate2Collection { appCert, - new X509Certificate2(rootCA.RawData) + X509CertificateLoader.LoadCertificate(rootCA.RawData) }; return result; diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs index 93637490d..37f36749b 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs @@ -111,7 +111,7 @@ KeyHashPair keyHashPair { rsa.ExportParameters(false); } - var plainCert = new X509Certificate2(cert.RawData); + var plainCert = X509CertificateLoader.LoadCertificate(cert.RawData); Assert.NotNull(plainCert); VerifyApplicationCert(app, plainCert); X509Utils.VerifyRSAKeyPair(cert, cert, true); @@ -143,7 +143,7 @@ KeyHashPair keyHashPair Assert.NotNull(cert); Assert.NotNull(cert.RawData); Assert.True(cert.HasPrivateKey); - using (var plainCert = new X509Certificate2(cert.RawData)) + using (var plainCert = X509CertificateLoader.LoadCertificate(cert.RawData)) { Assert.NotNull(plainCert); VerifyApplicationCert(app, plainCert, issuerCertificate); @@ -171,7 +171,7 @@ KeyHashPair keyHashPair Assert.NotNull(cert); Assert.NotNull(cert.RawData); Assert.True(cert.HasPrivateKey); - var plainCert = new X509Certificate2(cert.RawData); + var plainCert = X509CertificateLoader.LoadCertificate(cert.RawData); Assert.NotNull(plainCert); VerifyCACert(plainCert, subject, pathLengthConstraint); X509Utils.VerifyRSAKeyPair(cert, cert, true); @@ -220,7 +220,7 @@ KeyHashPair keyHashPair Assert.NotNull(rsa); } - using (var plainCert = new X509Certificate2(issuerCertificate.RawData)) + using (var plainCert = X509CertificateLoader.LoadCertificate(issuerCertificate.RawData)) { Assert.NotNull(plainCert); VerifyCACert(plainCert, issuerCertificate.Subject, pathLengthConstraint); @@ -285,7 +285,7 @@ public void ParseCertificateBlob() byte[] singleBlob = AsnUtils.ParseX509Blob(certBlob).ToArray(); Assert.NotNull(singleBlob); - var certX = new X509Certificate2(singleBlob); + var certX = X509CertificateLoader.LoadCertificate(singleBlob); Assert.NotNull(certX); Assert.AreEqual(certArray[0].RawData, singleBlob); Assert.AreEqual(singleBlob, certX.RawData); diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs index d77170d59..012ba43a0 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs @@ -118,7 +118,7 @@ public async Task VerifyAppCertX509Store(string storePath) CertificateStoreType.X509Store, storePath ); - using (var publicKey = new X509Certificate2(appCertificate.RawData)) + using (var publicKey = X509CertificateLoader.LoadCertificate(appCertificate.RawData)) { Assert.NotNull(publicKey); Assert.False(publicKey.HasPrivateKey); @@ -163,7 +163,7 @@ public async Task VerifyAppCertDirectoryStore() certificateStoreIdentifier, password ); - using (var publicKey = new X509Certificate2(appCertificate.RawData)) + using (var publicKey = X509CertificateLoader.LoadCertificate(appCertificate.RawData)) { Assert.NotNull(publicKey); Assert.False(publicKey.HasPrivateKey); diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs index 71466fbce..23a3f03f5 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs @@ -479,7 +479,7 @@ public async Task VerifyAppChainsOneTrusted() TestContext.Out.WriteLine($"InitValidator: {stopWatch.ElapsedMilliseconds - start}"); foreach (var app in m_goodApplicationTestSet) { - certValidator.Validate(new X509Certificate2(app.Certificate)); + certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate)); } TestContext.Out.WriteLine($"Validation: {stopWatch.ElapsedMilliseconds - start}"); } @@ -507,7 +507,7 @@ public async Task VerifyAppChainsAllButOneTrusted() var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - certValidator.Validate(new X509Certificate2(app.Certificate)); + certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate)); } } } @@ -535,7 +535,7 @@ public async Task VerifyAppChainsIncompleteChain() var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual((StatusCode)StatusCodes.BadCertificateChainIncomplete, (StatusCode)serviceResultException.StatusCode, serviceResultException.Message); } } @@ -569,7 +569,7 @@ public async Task VerifyAppChainsInvalidChain() var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual((StatusCode)StatusCodes.BadCertificateChainIncomplete, (StatusCode)serviceResultException.StatusCode, serviceResultException.Message); } } @@ -598,7 +598,7 @@ public async Task VerifyAppChainsWithGoodAndInvalidChain() var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - certValidator.Validate(new X509Certificate2(app.Certificate)); + certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate)); } } } @@ -631,7 +631,7 @@ public async Task VerifyRevokedTrustedStoreAppChains() var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual(v == kCaChainCount - 1 ? StatusCodes.BadCertificateRevoked : StatusCodes.BadCertificateIssuerRevoked, serviceResultException.StatusCode, serviceResultException.Message); } @@ -665,7 +665,7 @@ public async Task VerifyRevokedIssuerStoreAppChains() var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual(v == kCaChainCount - 1 ? StatusCodes.BadCertificateRevoked : StatusCodes.BadCertificateIssuerRevoked, serviceResultException.StatusCode, serviceResultException.Message); } @@ -698,12 +698,12 @@ public async Task VerifyRevokedIssuerStoreTrustedAppChains() } foreach (var app in m_goodApplicationTestSet) { - await validator.TrustedStore.Add(new X509Certificate2(app.Certificate)).ConfigureAwait(false); + await validator.TrustedStore.Add(X509CertificateLoader.LoadCertificate(app.Certificate)).ConfigureAwait(false); } var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual(v == kCaChainCount - 1 ? StatusCodes.BadCertificateRevoked : StatusCodes.BadCertificateIssuerRevoked, serviceResultException.StatusCode, serviceResultException.Message); } @@ -736,7 +736,7 @@ public async Task VerifyRevokedTrustedStoreNotTrustedAppChains() var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual(v == kCaChainCount - 1 ? StatusCodes.BadCertificateRevoked : StatusCodes.BadCertificateIssuerRevoked, serviceResultException.StatusCode, serviceResultException.Message); } @@ -768,12 +768,12 @@ public async Task VerifyRevokedTrustedStoreTrustedAppChains() } foreach (var app in m_goodApplicationTestSet) { - await validator.TrustedStore.Add(new X509Certificate2(app.Certificate)).ConfigureAwait(false); + await validator.TrustedStore.Add(X509CertificateLoader.LoadCertificate(app.Certificate)).ConfigureAwait(false); } var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual(v == kCaChainCount - 1 ? StatusCodes.BadCertificateRevoked : StatusCodes.BadCertificateIssuerRevoked, serviceResultException.StatusCode, serviceResultException.Message); } @@ -799,13 +799,13 @@ public async Task VerifyIssuerChainIncompleteTrustedAppCerts() // all app certs are trusted foreach (var app in m_goodApplicationTestSet) { - await validator.TrustedStore.Add(new X509Certificate2(app.Certificate)).ConfigureAwait(false); + await validator.TrustedStore.Add(X509CertificateLoader.LoadCertificate(app.Certificate)).ConfigureAwait(false); } var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - certValidator.Validate(new X509Certificate2(app.Certificate)); + certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate)); } } } @@ -834,13 +834,13 @@ public async Task VerifyIssuerChainTrustedAppCerts() // all app certs are trusted foreach (var app in m_goodApplicationTestSet) { - await validator.TrustedStore.Add(new X509Certificate2(app.Certificate)).ConfigureAwait(false); + await validator.TrustedStore.Add(X509CertificateLoader.LoadCertificate(app.Certificate)).ConfigureAwait(false); } var certValidator = validator.Update(); foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual((StatusCode)StatusCodes.BadCertificateChainIncomplete, (StatusCode)serviceResultException.StatusCode, serviceResultException.Message); } } @@ -859,9 +859,9 @@ public void VerifyPemWriterPrivateKeys() var pemDataBlob = PEMWriter.ExportPrivateKeyAsPEM(appCert); var pemString = Encoding.UTF8.GetString(pemDataBlob); TestContext.Out.WriteLine(pemString); - CertificateFactory.CreateCertificateWithPEMPrivateKey(new X509Certificate2(appCert.RawData), pemDataBlob); + CertificateFactory.CreateCertificateWithPEMPrivateKey(X509CertificateLoader.LoadCertificate(appCert.RawData), pemDataBlob); // note: password is ignored - var newCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(new X509Certificate2(appCert.RawData), pemDataBlob, "password"); + var newCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(X509CertificateLoader.LoadCertificate(appCert.RawData), pemDataBlob, "password"); X509Utils.VerifyRSAKeyPair(newCert, newCert, true); } } @@ -897,10 +897,10 @@ public void VerifyPemWriterRSAPrivateKeys() var pemDataBlob = PEMWriter.ExportRSAPrivateKeyAsPEM(appCert); var pemString = Encoding.UTF8.GetString(pemDataBlob); TestContext.Out.WriteLine(pemString); - var cert = CertificateFactory.CreateCertificateWithPEMPrivateKey(new X509Certificate2(appCert.RawData), pemDataBlob); + var cert = CertificateFactory.CreateCertificateWithPEMPrivateKey(X509CertificateLoader.LoadCertificate(appCert.RawData), pemDataBlob); Assert.NotNull(cert); // note: password is ignored - var newCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(new X509Certificate2(appCert.RawData), pemDataBlob, "password"); + var newCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(X509CertificateLoader.LoadCertificate(appCert.RawData), pemDataBlob, "password"); X509Utils.VerifyRSAKeyPair(newCert, newCert, true); } } @@ -1378,7 +1378,7 @@ public async Task VerifySomeMissingCRLRevokedTrustedStoreAppChains(bool rejectUn foreach (var app in m_goodApplicationTestSet) { - ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual(v == kCaChainCount - 1 ? StatusCodes.BadCertificateRevoked : StatusCodes.BadCertificateIssuerRevoked, serviceResultException.StatusCode, serviceResultException.Message); @@ -1421,7 +1421,7 @@ public async Task VerifyAllMissingCRLRevokedTrustedStoreAppChains() foreach (var app in m_goodApplicationTestSet) { - ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.IsTrue(StatusCodes.BadCertificateRevocationUnknown == serviceResultException.StatusCode, serviceResultException.Message); @@ -1483,7 +1483,7 @@ public async Task VerifySomeMissingCRLTrustedStoreAppChains(bool rejectUnknownRe { if (rejectUnknownRevocationStatus) { - ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + ServiceResultException serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual(v == kCaChainCount - 1 ? StatusCodes.BadCertificateRevocationUnknown : StatusCodes.BadCertificateIssuerRevocationUnknown, serviceResultException.StatusCode, @@ -1491,7 +1491,7 @@ public async Task VerifySomeMissingCRLTrustedStoreAppChains(bool rejectUnknownRe } else { - certValidator.Validate(new X509Certificate2(app.Certificate)); + certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate)); } } } @@ -1523,7 +1523,7 @@ public async Task VerifyMissingCRLANDAppChainsIncompleteChain(bool rejectUnknown foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual((StatusCode)StatusCodes.BadCertificateChainIncomplete, (StatusCode)serviceResultException.StatusCode, serviceResultException.Message); // no need to check for inner exceptions, since an incomplete chain error cannot be suppressed. } @@ -1547,12 +1547,12 @@ public async Task VerifyExistingCRLAppChainsExpiredCertificates(bool rejectUnkno { if (i != v || kCaChainCount == 1) { - await validator.TrustedStore.Add(new X509Certificate2(m_caChain[i].RawData)).ConfigureAwait(false); + await validator.TrustedStore.Add(X509CertificateLoader.LoadCertificate(m_caChain[i].RawData)).ConfigureAwait(false); await validator.TrustedStore.AddCRL(m_crlChain[i]).ConfigureAwait(false); } else { - await validator.IssuerStore.Add(new X509Certificate2(m_caChain[i].RawData)).ConfigureAwait(false); + await validator.IssuerStore.Add(X509CertificateLoader.LoadCertificate(m_caChain[i].RawData)).ConfigureAwait(false); await validator.IssuerStore.AddCRL(m_crlChain[i]).ConfigureAwait(false); } } @@ -1563,7 +1563,7 @@ public async Task VerifyExistingCRLAppChainsExpiredCertificates(bool rejectUnkno foreach (var app in m_notYetValidCertsApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual((StatusCode)StatusCodes.BadCertificateTimeInvalid, (StatusCode)serviceResultException.StatusCode, serviceResultException.Message); } } @@ -1602,7 +1602,7 @@ public async Task VerifyMissingCRLAppChainsExpiredCertificates(bool rejectUnknow foreach (var app in m_notYetValidCertsApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual((StatusCode)StatusCodes.BadCertificateTimeInvalid, (StatusCode)serviceResultException.StatusCode, serviceResultException.Message); // BadCertificateTimeInvalid can be suppressed. Ensure the other issues are caught, as well: @@ -1663,7 +1663,7 @@ public async Task VerifyMissingCRLNoTrust(bool rejectUnknownRevocationStatus) foreach (var app in m_goodApplicationTestSet) { - var serviceResultException = Assert.Throws(() => certValidator.Validate(new X509Certificate2(app.Certificate))); + var serviceResultException = Assert.Throws(() => certValidator.Validate(X509CertificateLoader.LoadCertificate(app.Certificate))); Assert.AreEqual((StatusCode)StatusCodes.BadCertificateUntrusted, (StatusCode)serviceResultException.StatusCode, serviceResultException.Message); } } diff --git a/Tests/Opc.Ua.Gds.Tests/ClientTest.cs b/Tests/Opc.Ua.Gds.Tests/ClientTest.cs index bff7f8ddd..462440233 100644 --- a/Tests/Opc.Ua.Gds.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Gds.Tests/ClientTest.cs @@ -794,7 +794,7 @@ public void StartGoodSigningRequests() } else { - csrCertificate = CertificateFactory.CreateCertificateWithPEMPrivateKey(new X509Certificate2(application.Certificate), application.PrivateKey, application.PrivateKeyPassword); + csrCertificate = CertificateFactory.CreateCertificateWithPEMPrivateKey(X509CertificateLoader.LoadCertificate(application.Certificate), application.PrivateKey, application.PrivateKeyPassword); } byte[] certificateRequest = CertificateFactory.CreateSigningRequest(csrCertificate, application.DomainNames); csrCertificate.Dispose(); @@ -1089,7 +1089,7 @@ public void GoodSigningRequestAsSelfAdmin() } else { - csrCertificate = CertificateFactory.CreateCertificateWithPEMPrivateKey(new X509Certificate2(application.Certificate), application.PrivateKey, application.PrivateKeyPassword); + csrCertificate = CertificateFactory.CreateCertificateWithPEMPrivateKey(X509CertificateLoader.LoadCertificate(application.Certificate), application.PrivateKey, application.PrivateKeyPassword); } byte[] certificateRequest = CertificateFactory.CreateSigningRequest(csrCertificate, application.DomainNames); csrCertificate.Dispose(); diff --git a/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestClient.cs b/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestClient.cs index e7ea4a97e..316312c47 100644 --- a/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestClient.cs +++ b/Tests/Opc.Ua.Gds.Tests/GlobalDiscoveryTestClient.cs @@ -206,7 +206,7 @@ public string ReadLogFile() #region Private Methods private async Task ApplyNewApplicationInstanceCertificateAsync(byte[] certificate, byte[] privateKey) { - using (var x509 = new X509Certificate2(certificate)) + using (var x509 = X509CertificateLoader.LoadCertificate(certificate)) { var certWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(x509, privateKey); m_client.Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(certWithPrivateKey); diff --git a/Tests/Opc.Ua.Gds.Tests/PushTest.cs b/Tests/Opc.Ua.Gds.Tests/PushTest.cs index 6b9cfb236..4c9f27210 100644 --- a/Tests/Opc.Ua.Gds.Tests/PushTest.cs +++ b/Tests/Opc.Ua.Gds.Tests/PushTest.cs @@ -83,7 +83,7 @@ protected async Task OneTimeSetUp() ConnectGDSClient(true); RegisterPushServerApplication(m_pushClient.PushClient.EndpointUrl); - m_selfSignedServerCert = new X509Certificate2(m_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate); + m_selfSignedServerCert = X509CertificateLoader.LoadCertificate(m_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate); m_domainNames = X509Utils.GetDomainsFromCertificate(m_selfSignedServerCert).ToArray(); await CreateCATestCerts(m_pushClient.TempStorePath).ConfigureAwait(false); @@ -328,7 +328,7 @@ public void UpdateCertificateSelfSignedNoPrivateKeyAsserts() { ConnectPushClient(true); using (X509Certificate2 invalidCert = CertificateFactory.CreateCertificate("uri:x:y:z", "TestApp", "CN=Push Server Test", null).CreateForRSA()) - using (X509Certificate2 serverCert = new X509Certificate2(m_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate)) + using (X509Certificate2 serverCert = X509CertificateLoader.LoadCertificate(m_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate)) { if (!X509Utils.CompareDistinguishedName(serverCert.Subject, serverCert.Issuer)) { @@ -358,7 +358,7 @@ public void UpdateCertificateSelfSignedNoPrivateKeyAsserts() public void UpdateCertificateSelfSignedNoPrivateKey() { ConnectPushClient(true); - using (X509Certificate2 serverCert = new X509Certificate2(m_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate)) + using (X509Certificate2 serverCert = X509CertificateLoader.LoadCertificate(m_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate)) { if (!X509Utils.CompareDistinguishedName(serverCert.Subject, serverCert.Issuer)) { @@ -627,7 +627,7 @@ public void GetCertificates() Assert.That(certificateTypeIds.Length == 1); Assert.NotNull(certificates[0]); - using (var x509 = new X509Certificate2(certificates[0])) + using (var x509 = X509CertificateLoader.LoadCertificate(certificates[0])) { Assert.NotNull(x509); } @@ -687,7 +687,7 @@ private X509Certificate2Collection CreateCertCollection(ByteStringCollection cer var result = new X509Certificate2Collection(); foreach (var rawCert in certList) { - result.Add(new X509Certificate2(rawCert)); + result.Add(X509CertificateLoader.LoadCertificate(rawCert)); } return result; } @@ -757,7 +757,7 @@ private async Task AddTrustListToStore(SecurityConfiguration config, Trust issuerCertificates = new X509Certificate2Collection(); foreach (var cert in trustList.IssuerCertificates) { - issuerCertificates.Add(new X509Certificate2(cert)); + issuerCertificates.Add(X509CertificateLoader.LoadCertificate(cert)); } } if ((masks & TrustListMasks.IssuerCrls) != 0) @@ -773,7 +773,7 @@ private async Task AddTrustListToStore(SecurityConfiguration config, Trust trustedCertificates = new X509Certificate2Collection(); foreach (var cert in trustList.TrustedCertificates) { - trustedCertificates.Add(new X509Certificate2(cert)); + trustedCertificates.Add(X509CertificateLoader.LoadCertificate(cert)); } } if ((masks & TrustListMasks.TrustedCrls) != 0) diff --git a/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs b/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs index e61ad47a1..8bfa910de 100644 --- a/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs +++ b/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs @@ -42,7 +42,7 @@ public static class X509TestUtils { public static void VerifyApplicationCertIntegrity(byte[] certificate, byte[] privateKey, string privateKeyPassword, string privateKeyFormat, byte[][] issuerCertificates) { - X509Certificate2 newCert = new X509Certificate2(certificate); + X509Certificate2 newCert = X509CertificateLoader.LoadCertificate(certificate); Assert.IsNotNull(newCert); X509Certificate2 newPrivateKeyCert = null; if (privateKeyFormat == "PFX") @@ -64,7 +64,7 @@ public static void VerifyApplicationCertIntegrity(byte[] certificate, byte[] pri CertificateIdentifierCollection issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var issuer in issuerCertificates) { - var issuerCert = new X509Certificate2(issuer); + var issuerCert = X509CertificateLoader.LoadCertificate(issuer); Assert.IsNotNull(issuerCert); issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert)); } @@ -85,8 +85,8 @@ public static void VerifyApplicationCertIntegrity(byte[] certificate, byte[] pri public static void VerifySignedApplicationCert(ApplicationTestData testApp, byte[] rawSignedCert, byte[][] rawIssuerCerts) { - X509Certificate2 signedCert = new X509Certificate2(rawSignedCert); - X509Certificate2 issuerCert = new X509Certificate2(rawIssuerCerts[0]); + X509Certificate2 signedCert = X509CertificateLoader.LoadCertificate(rawSignedCert); + X509Certificate2 issuerCert = X509CertificateLoader.LoadCertificate(rawIssuerCerts[0]); TestContext.Out.WriteLine($"Signed cert: {signedCert}"); TestContext.Out.WriteLine($"Issuer cert: {issuerCert}"); diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs index 536f78fd0..a6302d905 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs @@ -174,7 +174,7 @@ public void CrlBuilderTest(bool empty, bool noExtensions, KeyHashPair keyHashPai Assert.AreEqual(2, x509Crl.CrlExtensions.Count); } - using (var issuerPubKey = new X509Certificate2(m_issuerCert.RawData)) + using (var issuerPubKey = X509CertificateLoader.LoadCertificate(m_issuerCert.RawData)) { Assert.True(x509Crl.VerifySignature(issuerPubKey, true)); } @@ -219,7 +219,7 @@ public void CrlBuilderTestWithSignatureGenerator(KeyHashPair keyHashPair) Assert.AreEqual(serial, x509Crl.RevokedCertificates[0].UserCertificate); Assert.AreEqual(serstring, x509Crl.RevokedCertificates[1].SerialNumber); Assert.AreEqual(2, x509Crl.CrlExtensions.Count); - using (var issuerPubKey = new X509Certificate2(m_issuerCert.RawData)) + using (var issuerPubKey = X509CertificateLoader.LoadCertificate(m_issuerCert.RawData)) { Assert.True(x509Crl.VerifySignature(issuerPubKey, true)); } diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestUtils.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestUtils.cs index 2f2cc4a85..feb037b27 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestUtils.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestUtils.cs @@ -193,7 +193,7 @@ public void Initialize(byte[] blob, string path) Cert = blob; try { - X509Certificate = new X509Certificate2(path); + X509Certificate = X509CertificateLoader.LoadCertificateFromFile(path); } catch { } diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs index 2c2d24ab7..767f96a23 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs @@ -304,7 +304,7 @@ ECCurveHashPair ecCurveHashPair { var generator = X509SignatureGenerator.CreateForECDsa(ecdsaPrivateKey); var cert = CertificateBuilder.Create("CN=App Cert") - .SetIssuer(new X509Certificate2(signingCert.RawData)) + .SetIssuer(X509CertificateLoader.LoadCertificate(signingCert.RawData)) .CreateForRSA(generator); Assert.NotNull(cert); WriteCertificate(cert, "Default signed ECDsa cert"); @@ -316,7 +316,7 @@ ECCurveHashPair ecCurveHashPair var generator = X509SignatureGenerator.CreateForECDsa(ecdsaPrivateKey); var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(ecCurveHashPair.HashAlgorithmName) - .SetIssuer(new X509Certificate2(signingCert.RawData)) + .SetIssuer(X509CertificateLoader.LoadCertificate(signingCert.RawData)) .SetECDsaPublicKey(ecdsaPublicKey) .CreateForECDsa(generator); Assert.NotNull(cert); @@ -328,7 +328,7 @@ ECCurveHashPair ecCurveHashPair var generator = X509SignatureGenerator.CreateForECDsa(ecdsaPrivateKey); var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(ecCurveHashPair.HashAlgorithmName) - .SetIssuer(new X509Certificate2(signingCert.RawData)) + .SetIssuer(X509CertificateLoader.LoadCertificate(signingCert.RawData)) .SetECCurve(ecCurveHashPair.Curve) .CreateForECDsa(generator); Assert.NotNull(cert); diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs index e9563031e..7abef4c8f 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs @@ -350,7 +350,7 @@ public void CreateIssuerRSAWithSuppliedKeyPair() .CreateForRSA(generator)) { Assert.NotNull(cert); - issuer = new X509Certificate2(cert.RawData); + issuer = X509CertificateLoader.LoadCertificate(cert.RawData); WriteCertificate(cert, "Default root cert with supplied RSA cert"); CheckPEMWriter(cert); } @@ -388,7 +388,7 @@ public void CreateIssuerRSACngWithSuppliedKeyPair() .CreateForRSA(generator)) { Assert.NotNull(cert); - issuer = new X509Certificate2(cert.RawData); + issuer = X509CertificateLoader.LoadCertificate(cert.RawData); WriteCertificate(cert, "Default root cert with supplied RSA cert"); CheckPEMWriter(cert); } @@ -425,7 +425,7 @@ KeyHashPair keyHashPair using (RSA rsaPrivateKey = signingCert.GetRSAPrivateKey()) { var generator = X509SignatureGenerator.CreateForRSA(rsaPrivateKey, RSASignaturePadding.Pkcs1); - using (var issuer = new X509Certificate2(signingCert.RawData)) + using (var issuer = X509CertificateLoader.LoadCertificate(signingCert.RawData)) using (var cert = CertificateBuilder.Create("CN=App Cert") .SetIssuer(issuer) .CreateForRSA(generator)) @@ -442,7 +442,7 @@ KeyHashPair keyHashPair using (RSA rsaPublicKey = signingCert.GetRSAPublicKey()) { var generator = X509SignatureGenerator.CreateForRSA(rsaPrivateKey, RSASignaturePadding.Pkcs1); - using (var issuer = new X509Certificate2(signingCert.RawData)) + using (var issuer = X509CertificateLoader.LoadCertificate(signingCert.RawData)) using (var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(keyHashPair.HashAlgorithmName) .SetIssuer(issuer) @@ -457,7 +457,7 @@ KeyHashPair keyHashPair using (RSA rsaPrivateKey = signingCert.GetRSAPrivateKey()) { var generator = X509SignatureGenerator.CreateForRSA(rsaPrivateKey, RSASignaturePadding.Pkcs1); - using (var issuer = new X509Certificate2(signingCert.RawData)) + using (var issuer = X509CertificateLoader.LoadCertificate(signingCert.RawData)) using (var cert = CertificateBuilder.Create("CN=App Cert") .SetHashAlgorithm(keyHashPair.HashAlgorithmName) .SetIssuer(issuer) diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs b/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs index 5078a0264..a574e1282 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs @@ -56,7 +56,7 @@ public void DecodeExtensions( CertificateAsset certAsset ) { - using (var x509Cert = new X509Certificate2(certAsset.Cert)) + using (var x509Cert = X509CertificateLoader.LoadCertificate(certAsset.Cert)) { Assert.NotNull(x509Cert); TestContext.Out.WriteLine("CertificateAsset:"); diff --git a/Tests/customtest.bat b/Tests/customtest.bat index 7ae1bbecb..fef271ed2 100644 --- a/Tests/customtest.bat +++ b/Tests/customtest.bat @@ -2,19 +2,19 @@ setlocal enabledelayedexpansion echo This script is used to run custom platform tests for the UA Core Library -echo Supported parameters: net462, netstandard2.0, netstandard2.1, net472, net48, net6.0, net8.0 +echo Supported parameters: net462, netstandard2.0, netstandard2.1, net472, net48, net6.0, net8.0, net 9.0 REM Check if the target framework parameter is provided if "%1"=="" ( echo Usage: %0 [TargetFramework] - echo Allowed values for TargetFramework: net462, netstandard2.0, netstandard2.1, net472, net48, net6.0, net8.0, default + echo Allowed values for TargetFramework: net462, netstandard2.0, netstandard2.1, net472, net48, net6.0, net8.0, net9.0, default goto :eof ) REM Check if the provided TargetFramework is valid -set "validFrameworks= default net462 net472 netstandard2.0 netstandard2.1 net48 net6.0 net8.0 " +set "validFrameworks= default net462 net472 netstandard2.0 netstandard2.1 net48 net6.0 net8.0 net9.0 " if "!validFrameworks: %1 =!"=="%validFrameworks%" ( - echo Invalid TargetFramework specified. Allowed values are: default, net462, net472 netstandard2.0, netstandard2.1, net48, net6.0, net8.0 + echo Invalid TargetFramework specified. Allowed values are: default, net462, net472 netstandard2.0, netstandard2.1, net48, net6.0, net8.0, net9.0 goto :eof ) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 1d2ede8b5..0be491de2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -102,6 +102,16 @@ stages: framework: net8.0 configuration: Release jobnamesuffix: net80 +- stage: testnet90 + dependsOn: [build] + displayName: 'Test .NET 9.0' + condition: and(succeeded(), ne(variables.ScheduledBuild, 'False')) + jobs: + - template: .azurepipelines/test.yml + parameters: + framework: net9.0 + configuration: Release + jobnamesuffix: net90 - stage: testnet462 dependsOn: [build] displayName: 'Test .NET 4.6.2' diff --git a/targets.props b/targets.props index 17b539d7c..b1cf79a21 100644 --- a/targets.props +++ b/targets.props @@ -12,7 +12,7 @@ A build with all custom targets which are not part of a regular build is scheduled once a week in the DevOps build pipeline. Uncomment the following lines to test a custom test target - supported values: net462, netstandard2.0, netstandard2.1, net472, net48, net6.0, net8.0 + supported values: net462, netstandard2.0, netstandard2.1, net472, net48, net6.0, net8.0, net9.0 --> - + - preview-all - net8.0;net6.0;net48 - net8.0 - net48;net8.0 - net472;net48;netstandard2.0;netstandard2.1;net6.0;net8.0 - net472;net48;netstandard2.0;netstandard2.1;net6.0;net8.0 - net462;net472;net48;netstandard2.1;net6.0;net8.0 - net472;net48;netstandard2.0;netstandard2.1;net6.0;net8.0 + preview + all + default + net9.0;net6.0;net48 + net9.0 + net48;net9.0 + net472;net48;netstandard2.0;netstandard2.1;net6.0;net8.0;net9.0 + net472;net48;netstandard2.0;netstandard2.1;net6.0;net8.0;net9.0 + net462;net472;net48;netstandard2.1;net6.0;net8.0;net9.0 + net472;net48;netstandard2.0;netstandard2.1;net6.0;net8.0;net9.0