You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A System.Security.Cryptography.CryptographicException with message "Hash algorithm 1.2.840.113549.1.1.2 is not supported." occurs during connection to an OPC UA server when there is a certificate on a certificate revocation list (CRL) in the Windows certificate store which has an unsupported hash algorithm (in my specific case MD2 with OID 1.2.840.113549.1.1.2) even if it is not associated with OPC UA in any way. The error occurs in Opc.Ua.X509CertificateStore in line 255 because the IssuerName could not be extracted due to the unknown hash.
Expected Behavior
The CryptographicException should not fail the connection to the OPC UA server. If the certificate really belongs to the OPC UA connection the connection fails at a later point anyway.
Steps To Reproduce
Operating system: Microsoft Windows 10
Tested with commit 0b23e5f on branch release/1.5.374
Have a certificate with an invalid hash (example MD2) in the CRL of Intermediate Certification Authorities in the Windows certificate store (I was not able to find a way to create a certificate with an invalid hash and add it to a revocation list so I cannot give instructions on this)
Create a new C# console project with the name OpcUaExample and .NET 8
Add the project Opc.Ua.Client.csproj from UA-.NETStandard/Libraries/Opc.Ua.Client and Opc.Ua.Core.csproj from UA-.NETStandard/Stack/Opc.Ua.Core to the solution
Add a project reference to Opc.Ua.Client to OpcUaExample
Replace the contents of Program.cs with the following:
using Opc.Ua;using Opc.Ua.Client;using Opc.Ua.Configuration;using ISession = Opc.Ua.Client.ISession;namespace OpcUaExample;/// <summary>/// Class containing the entry point of the program./// </summary>publicclassProgram{/// <summary>/// Entry point of the program./// </summary>/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>publicstaticasync Task Main(){usingOpcUaSessionKeeperopcUaSessionKeeper=new("opc.tcp://localhost:62541/Quickstarts/ReferenceServer");await opcUaSessionKeeper.ConnectOpcUaSession();}}/// <summary>/// Class to manage a OPC UA session./// </summary>publicclassOpcUaSessionKeeper:IDisposable{privatereadonlystring_opcUaUri;privateISession?_opcUaSession;privatereadonlyushort_opcUaCertificateLifetimeInMonths=180;/// <summary>/// Constructor to instantiate an <see cref="OpcUaSessionKeeper"/>./// </summary>publicOpcUaSessionKeeper(stringuri){_opcUaUri=uri;}/// <inheritdoc/>publicvoidDispose(){
DisconnectOpcUaSession().Wait();}/// <summary>/// Creates a new OPC UA <see cref="ISession"/> and connects to it./// </summary>publicasync Task ConnectOpcUaSession(){// define the OPC UA client applicationApplicationInstanceapplication=new(){ApplicationType= ApplicationType.Client,};// load the application configurationstringapplicationConfigurationFilePath= Path.Combine(AppContext.BaseDirectory,"OpcUaExample.Config.xml");ApplicationConfigurationconfig=await application.LoadApplicationConfiguration(applicationConfigurationFilePath, silent:false);try{// check the application certificate.await application.CheckApplicationInstanceCertificate(silent:false, minimumKeySize:0, _opcUaCertificateLifetimeInMonths);}catch(Exceptionex){stringbaseLoggingMessage="Exception occured during check of certificate.";
Console.WriteLine("{0} Cause: {1}: {2}.", baseLoggingMessage, ex.GetType(), ex.Message);// try deleting the old certificate and creating a new oneawait application.DeleteApplicationInstanceCertificate();
application.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate =null;// create a new application certificateawait application.CheckApplicationInstanceCertificate(silent:false, minimumKeySize:0, _opcUaCertificateLifetimeInMonths);
Console.WriteLine("Deleted the old application certificate and created a new one successfully.");}// SessionTimeOut >= KeepAliveTimeoutuintsessionTimeOutMs=(uint)TimeSpan.FromSeconds(60).TotalMilliseconds;intkeepAliveIntervalMs=(int)TimeSpan.FromSeconds(30).TotalMilliseconds;stringserverUri= _opcUaUri;UserIdentity?userIdentity=null;
Console.WriteLine("Connecting to OPC UA server {0}.", serverUri);// configure endpoint for OPC UAEndpointDescriptionendpointDescription= CoreClientUtils.SelectEndpoint(config, serverUri, useSecurity:true);EndpointConfigurationendpointConfiguration= EndpointConfiguration.Create(config);ConfiguredEndpointendpoint=new(null, endpointDescription, endpointConfiguration);Sessionsession=await Session.Create(
config,
endpoint,
updateBeforeConnect:false,
sessionName: config.ApplicationName,
sessionTimeOutMs,
userIdentity,
preferredLocales:null);
session.KeepAliveInterval =keepAliveIntervalMs;
Console.WriteLine("New session for OPC UA created with session name {0} for server {1}.", session.SessionName, serverUri);_opcUaSession=session;}/// <summary>/// Closes the OPC UA <see cref="ISession"/> if a connection exists./// </summary>publicasync Task DisconnectOpcUaSession(){if(_opcUaSession==null){return;}
_opcUaSession.KeepAlive -=RecoverSessionOnError;await _opcUaSession.CloseAsync();
_opcUaSession.Dispose();}}
Create a file OpcUaExample.Config.xml and paste the following:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationConfigurationxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:ua="http://opcfoundation.org/UA/2008/02/Types.xsd"xmlns="http://opcfoundation.org/UA/SDK/Configuration.xsd"
>
<ApplicationName>OpcUaExample</ApplicationName>
<ApplicationUri>urn:localhost:OpcUaExample</ApplicationUri>
<ApplicationType>Client_1</ApplicationType>
<SecurityConfiguration>
<!-- Where the application instance certificate is stored (MachineDefault) -->
<ApplicationCertificate>
<StoreType>X509Store</StoreType>
<StorePath>CurrentUser\My</StorePath>
<SubjectName>CN=OpcUaExample,DC=localhost</SubjectName>
</ApplicationCertificate>
<!-- Where the issuer certificate are stored (certificate authorities) -->
<TrustedIssuerCertificates>
<StoreType>X509Store</StoreType>
<StorePath>CurrentUser\Ca</StorePath>
</TrustedIssuerCertificates>
<!-- Where the trust list is stored -->
<TrustedPeerCertificates>
<StoreType>X509Store</StoreType>
<StorePath>CurrentUser\TrustedPeople</StorePath>
</TrustedPeerCertificates>
<!-- The directory used to store invalid certficates for later review by the administrator. -->
<RejectedCertificateStore>
<StoreType>X509Store</StoreType>
<StorePath>CurrentUser\Disallowed</StorePath>
</RejectedCertificateStore>
<!-- WARNING: The following setting (to automatically accept untrusted certificates) should be used for easy debugging purposes ONLY and turned off for production deployments! -->
<AutoAcceptUntrustedCertificates>true</AutoAcceptUntrustedCertificates>
<!-- WARNING: SHA1 signed certficates are by default rejected and should be phased out. only nano and embedded profiles are allowed to use sha1 signed certificates. -->
<RejectSHA1SignedCertificates>true</RejectSHA1SignedCertificates>
<RejectUnknownRevocationStatus>true</RejectUnknownRevocationStatus>
<MinimumCertificateKeySize>2048</MinimumCertificateKeySize>
<AddAppCertToTrustedStore>false</AddAppCertToTrustedStore>
<SendCertificateChain>true</SendCertificateChain>
<!-- Where the User trust list is stored-->
<TrustedUserCertificates>
<StoreType>X509Store</StoreType>
<StorePath>CurrentUser\AddressBook</StorePath>
</TrustedUserCertificates>
</SecurityConfiguration>
<TransportConfigurations></TransportConfigurations>
<TransportQuotas>
<OperationTimeout>120000</OperationTimeout>
<MaxStringLength>4194304</MaxStringLength>
<MaxByteStringLength>4194304</MaxByteStringLength>
<MaxArrayLength>65535</MaxArrayLength>
<MaxMessageSize>4194304</MaxMessageSize>
<MaxBufferSize>65535</MaxBufferSize>
<ChannelLifetime>300000</ChannelLifetime>
<SecurityTokenLifetime>3600000</SecurityTokenLifetime>
</TransportQuotas>
<ClientConfiguration>
<DefaultSessionTimeout>60000</DefaultSessionTimeout>
<WellKnownDiscoveryUrls>
<ua:String>opc.tcp://{0}:4840</ua:String>
<ua:String>http://{0}:52601/UADiscovery</ua:String>
<ua:String>http://{0}/UADiscovery/Default.svc</ua:String>
</WellKnownDiscoveryUrls>
<DiscoveryServers></DiscoveryServers>
<MinSubscriptionLifetime>10000</MinSubscriptionLifetime>
<OperationLimits>
<MaxNodesPerRead>2500</MaxNodesPerRead>
<MaxNodesPerHistoryReadData>1000</MaxNodesPerHistoryReadData>
<MaxNodesPerHistoryReadEvents>1000</MaxNodesPerHistoryReadEvents>
<MaxNodesPerWrite>2500</MaxNodesPerWrite>
<MaxNodesPerHistoryUpdateData>1000</MaxNodesPerHistoryUpdateData>
<MaxNodesPerHistoryUpdateEvents>1000</MaxNodesPerHistoryUpdateEvents>
<MaxNodesPerMethodCall>2500</MaxNodesPerMethodCall>
<MaxNodesPerBrowse>2500</MaxNodesPerBrowse>
<MaxNodesPerRegisterNodes>2500</MaxNodesPerRegisterNodes>
<MaxNodesPerTranslateBrowsePathsToNodeIds>2500</MaxNodesPerTranslateBrowsePathsToNodeIds>
<MaxNodesPerNodeManagement>2500</MaxNodesPerNodeManagement>
<MaxMonitoredItemsPerCall>2500</MaxMonitoredItemsPerCall>
</OperationLimits>
</ClientConfiguration>
</ApplicationConfiguration>
Make sure that the configuration file is copied to output directory, e.g. with adding the following to OpcUaExample.csproj:
Here is the crl containing the certificate with an MD2 hash. The file extension must be changed back from .crl.txt to .crl due to GitHub not allowing the upload of a file with .crl. cert_with_md2_hash.crl.txt
Type of issue
Current Behavior
A
System.Security.Cryptography.CryptographicException
with message "Hash algorithm 1.2.840.113549.1.1.2 is not supported." occurs during connection to an OPC UA server when there is a certificate on a certificate revocation list (CRL) in the Windows certificate store which has an unsupported hash algorithm (in my specific case MD2 with OID 1.2.840.113549.1.1.2) even if it is not associated with OPC UA in any way. The error occurs in Opc.Ua.X509CertificateStore in line 255 because theIssuerName
could not be extracted due to the unknown hash.Expected Behavior
The
CryptographicException
should not fail the connection to the OPC UA server. If the certificate really belongs to the OPC UA connection the connection fails at a later point anyway.Steps To Reproduce
CryptographicException
due to an unsupported hash algorithm of a certificateEnvironment
Anything else?
Log
Suggested fix
File: https://github.com/OPCFoundation/UA-.NETStandard/blob/release/1.5.374/Stack/Opc.Ua.Core/Security/Certificates/X509CertificateStore/X509CertificateStore.cs
Line: 254 (first in
foreach
)The text was updated successfully, but these errors were encountered: