QuickOPC User's Guide and Reference
Providing OPC UA Client Instance Certificate
Fundamentals > Security > OPC UA Client-Server Security > Providing OPC UA Client Instance Certificate
In This Topic

Similarly to server instance certificate checking described above, in a secured OPC-UA solution, the OPC client identifies itself to the OPC server using its own instance certificate. The OPC server authenticates the certificate and checks whether the communication with that OPC client is authorized. Typically, the process of checking other party’s instance certificate is achieved through use of certificate trust lists, accessible programmatically and by means of UA Configuration Tool (installed with our product, and with OPC-UA downloads provided by OPC Foundation).

Since with QuickOPC-UA you are developing an OPC-UA client application, this client application must therefore typically provide its instance certificate to the OPC servers it is connecting to. QuickOPC-UA attempts to make this process easier by automatically selecting parameters for the certificate, and if the certificate does not exist yet, by creating it and storing into the appropriate certificate store on the computer. Depending on your deployment scenario, you may also create the certificate and put it into the certificate store by some other means, and in that case, you would simply let QuickOPC-UA use that certificate.

When the effective endpoint selection policy only allows connection with no message security, the client instance certificate is not used (and not required) when creating the OPC UA session.

.NET

// This example demonstrates how to set the application name for the client certificate.

using System;
using OpcLabs.BaseLib.Instrumentation;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.Application;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._UAApplicationManifest
{
    class ApplicationName
    {
        public static void Main1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            // Hook static events
            EasyUAClient.LogEntry += EasyUAClientOnLogEntry;

            try
            {
                // Set the application name, which determines the subject of the client certificate.
                // Note that this only works once in each host process.
                EasyUAApplication.Instance.ApplicationParameters.ApplicationManifest.ApplicationName = 
                    "QuickOPC - CSharp example application";

                // Do something - invoke an OPC read, to trigger some loggable entries.
                var client = new EasyUAClient();
                try
                {
                    client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853");
                }
                catch (UAException uaException)
                {
                    Console.WriteLine("*** Failure: {0}", uaException.GetBaseException().Message);
                }

                // The certificate will be located or created in a directory similar to:
                // C:\ProgramData\OPC Foundation\CertificateStores\MachineDefault\certs
                // and its subject will be as given by the application name.

                Console.WriteLine("Processing log entry events for 10 seconds...");
                System.Threading.Thread.Sleep(10 * 1000);

                Console.WriteLine("Finished.");
            }
            finally
            {
                // Unhook static events
                EasyUAClient.LogEntry -= EasyUAClientOnLogEntry;
            }
        }

        // Event handler for the LogEntry event.
        // Print the loggable entry containing client certificate parameters.
        private static void EasyUAClientOnLogEntry(object sender, LogEntryEventArgs logEntryEventArgs)
        {
            if (logEntryEventArgs.EventId == 161)
                Console.WriteLine(logEntryEventArgs);
        }
    }
}
# This example demonstrates how to set the application name for the client certificate.

# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.Application import *
from OpcLabs.EasyOpc.UA.OperationModel import *


# Event handler for the LogEntry event.
# Print the loggable entry containing client certificate parameters.
def onLogEntry(sender, logEntryEventArgs):
    if logEntryEventArgs.EventId == 161:
        print(logEntryEventArgs)


endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'

# Hook static events.
EasyUAClient.LogEntry += onLogEntry

try:
    # Set the application name, which determines the subject of the client certificate.
    # Note that this only works once in each host process.
    EasyUAApplication.Instance.ApplicationParameters.ApplicationManifest.ApplicationName = \
        'QuickOPC - Python (.NET) example application'

    # Do something - invoke an OPC read, to trigger some loggable entries.
    client = EasyUAClient()
    try:
        value = IEasyUAClientExtension.ReadValue(client,
                                                 endpointDescriptor,
                                                 UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10853'))
    except UAException as uaException:
        print('*** Failure: ' + uaException.GetBaseException().Message)

    # The certificate will be located or created in a directory similar to:
    # C:\ProgramData\OPC Foundation\CertificateStores\MachineDefault\certs
    # and its subject will be as given by the application name.

    print('Processing log entry events for 10 seconds...')
    time.sleep(10)

    print('Finished.')

finally:
    # Unhook static events.
    EasyUAClient.LogEntry -= onLogEntry
' This example demonstrates how to set the application name for the client certificate.

Imports OpcLabs.BaseLib.Instrumentation
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.Application
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace _UAApplicationManifest
    Friend Class ApplicationName
        Public Shared Sub Main1()

            Dim endpointDescriptor As UAEndpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            ' Hook static events
            AddHandler EasyUAClient.LogEntry, AddressOf EasyUAClientOnLogEntry

            Try
                ' Set the application name, which determines the subject of the client certificate.
                ' Note that this only works once in each host process.
                EasyUAApplication.Instance.ApplicationParameters.ApplicationManifest.ApplicationName =
                    "QuickOPC - VBNet example application"

                ' Do something - invoke an OPC read, to trigger some loggable entries.
                Dim client = New EasyUAClient()
                Try
                    client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853")
                Catch uaException As UAException
                    Console.WriteLine("*** Failure: {0}", uaException.GetBaseException.Message)
                    Exit Sub
                End Try

                ' The certificate will be located or created in a directory similar to:
                ' C:\ProgramData\OPC Foundation\CertificateStores\MachineDefault\certs
                ' and its subject will be as given by the application name.

                Console.WriteLine("Processing log entry events for 10 seconds...")
                Threading.Thread.Sleep(10 * 1000)

                Console.WriteLine("Finished.")
            Finally
                ' Unhook static events
                RemoveHandler EasyUAClient.LogEntry, AddressOf EasyUAClientOnLogEntry
            End Try

        End Sub


        ' Event handler for the LogEntry event.
        ' Print the loggable entry containing client certificate parameters.
        Private Shared Sub EasyUAClientOnLogEntry(ByVal sender As Object, ByVal logEntryEventArgs As LogEntryEventArgs)
            If (logEntryEventArgs.EventId = 161) Then
                Console.WriteLine(logEntryEventArgs)
            End If
        End Sub
    End Class
End Namespace

COM

// This example demonstrates how to set the application name for the client certificate.

type
  TClientManagementEventHandlers103 = class
    procedure OnLogEntry(
      ASender: TObject;
      sender: OleVariant;
      const eventArgs: _LogEntryEventArgs);
  end;

// Event handler for the LogEntry event.
// Print the loggable entry containing client certificate parameters.
procedure TClientManagementEventHandlers103.OnLogEntry(
  ASender: TObject;
  sender: OleVariant;
  const eventArgs: _LogEntryEventArgs);
begin
  if eventArgs.EventId = 161 then
      WriteLn(eventArgs.ToString);
end;

class procedure ApplicationName.Main;
var
  Application: TEasyUAApplication;
  Client: OpcLabs_EasyOpcUA_TLB._EasyUAClient;
  ClientManagement: TEasyUAClientManagement;
  ClientManagementEventHandlers: TClientManagementEventHandlers103;
  Value: OleVariant;
begin
  // The configuration object allows access to static behavior - here, the
  // shared LogEntry event.
  ClientManagement := TEasyUAClientManagement.Create(nil);
  ClientManagementEventHandlers := TClientManagementEventHandlers103.Create;
  ClientManagement.OnLogEntry := ClientManagementEventHandlers.OnLogEntry;
  ClientManagement.Connect;

  // Obtain the application interface.
  Application := TEasyUAApplication.Create(nil);

  try
    // Set the application name, which determines the subject of the client certificate.
    // Note that this only works once in each host process.
    Application.ApplicationParameters.ApplicationManifest.ApplicationName :=
      'QuickOPC - Delphi example application';

    // Do something - invoke an OPC read, to trigger some loggable entries.
    Client := CoEasyUAClient.Create;
    try
      Value := Client.ReadValue(
      //'http://opcua.demo-this.com:51211/UA/SampleServer',
      //'https://opcua.demo-this.com:51212/UA/SampleServer/',
      'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer',
      'nsu=http://test.org/UA/Data/ ;i=10853');
    except
      on E: EOleException do
      begin
        WriteLn(Format('*** Failure: %s', [E.GetBaseException.Message]));
      end;
    end;

    // The certificate will be located or created in a directory similar to:
    // C:\ProgramData\OPC Foundation\CertificateStores\MachineDefault\certs
    // and its subject will be as given by the application name.

    WriteLn('Processing log entry events for 10 seconds...');
    PumpSleep(10*1000);

    WriteLn('Finished...');
  finally
    FreeAndNil(Application);
    FreeAndNil(ClientManagement);
    FreeAndNil(ClientManagementEventHandlers);
  end;
end;
// This example demonstrates how to set the application name for the client certificate.

class ClientManagementEvents {
    // Event handler for the LogEntry event.
    // Print the loggable entry containing client certificate parameters.
    function LogEntry($Sender, $E)
    {
        if ($E->EventId == 161)
            printf("%s\n", $E);
    }
}

// The management object allows access to static behavior - here, the
// shared LogEntry event.
$ClientManagement = new COM("OpcLabs.EasyOpc.UA.EasyUAClientManagement");
$ClientManagementEvents = new ClientManagementEvents();
com_event_sink($ClientManagement, $ClientManagementEvents, "DEasyUAClientManagementEvents");

// Obtain the application interface.
$Application = new COM("OpcLabs.EasyOpc.UA.Application.EasyUAApplication");

// Set the application name, which determines the subject of the client certificate.
// Note that this only works once in each host process.
$Application->ApplicationParameters->ApplicationManifest->ApplicationName = "QuickOPC - PHP example application";

// Do something - invoke an OPC read, to trigger some loggable entries.
$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
try
{
    $value = $Client->ReadValue(
        //"http://opcua.demo-this.com:51211/UA/SampleServer", 
        "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", 
        "nsu=http://test.org/UA/Data/ ;i=10853");
}
catch (com_exception $e)
{
    printf("*** Failure: %s\n", $e->getMessage());
}

// The certificate will be located or created in a directory similar to:
// C:\ProgramData\OPC Foundation\CertificateStores\MachineDefault\certs
// and its subject will be as given by the application name.

printf("Processing log entry events for 10 seconds...");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 10);

printf("Finished.\n");
Rem This example demonstrates how to set the application name for the client certificate.

Private Sub ApplicationName_Main_Command_Click()
    OutputText = ""
    
    ' Obtain the application interface
    Dim Application As New EasyUAApplication
        
    ' Set the application name, which determines the subject of the client certificate.
    ' Note that this only works once in each host process.
    Application.ApplicationParameters.ApplicationManifest.applicationName = "QuickOPC - VB6 example application"

    ' Do something - invoke an OPC read, to trigger some loggable entries.
    Dim client As New EasyUAClient
    On Error Resume Next
    Dim value As Variant
    value = client.ReadValue("opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853")
    If Err.Number <> 0 Then
        OutputText = OutputText & "*** Failure: " & Err.Source & ": " & Err.Description & vbCrLf
        Exit Sub
    End If
    On Error GoTo 0

    ' The certificate will be located or created in a directory similar to:
    ' C:\ProgramData\OPC Foundation\CertificateStores\MachineDefault\certs
    ' and its subject will be as given by the application name.

    OutputText = OutputText & "Processing log entry events for 10 seconds..." & vbCrLf
    Pause 10000
    
    Set Application = Nothing
    OutputText = OutputText & "Finished..." & vbCrLf
End Sub
' Event handler for the LogEntry event. It simply prints out the event.
Private Sub ClientManagement1_LogEntry(ByVal sender As Variant, ByVal eventArgs As OpcLabs_BaseLib.LogEntryEventArgs)
    If eventArgs.eventId = 161 Then
        OutputText = OutputText & eventArgs & vbCrLf
    End If
End Sub
Rem This example demonstrates how to set the application name for the client certificate.

Option Explicit

' The management object allows access to static behavior.
WScript.Echo "Obtaining the client management object..."
Dim ClientManagement: Set ClientManagement = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClientManagement")
WScript.ConnectObject ClientManagement, "ClientManagement_"

WScript.Echo "Obtaining the application interface..."
Dim Application: Set Application = CreateObject("OpcLabs.EasyOpc.UA.Application.EasyUAApplication")

' Set the application name, which determines the subject of the client certificate.
' Note that this only works once in each host process.
WScript.Echo "Setting the application name..."
Application.ApplicationParameters.ApplicationManifest.ApplicationName = "QuickOPC - VBScript example application"

WScript.Echo "Creating a client object..."
Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")

' Do something - invoke an OPC read, to trigger some loggable entries.
WScript.Echo "Reading a value..."
On Error Resume Next
Dim value: value = Client.ReadValue("opc.tcp://opcua.demo-this.com:51210/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853")
If Err.Number <> 0 Then
    WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description
    WScript.Quit
End If
On Error Goto 0

' The certificate will be located or created in a directory similar to:
' C:\Users\All Users\OPC Foundation\CertificateStores\UA Applications\certs\
' and its subject will be as given by the application name.

WScript.Echo "Processing log entry events for 10 seconds..."
WScript.Sleep 10*1000

WScript.Echo "Finished."



' Event handler for the LogEntry event.
' Print the loggable entry containing client certificate parameters.
Sub ClientManagement_LogEntry(Sender, e)
    If e.EventId = 161 Then WScript.Echo e
End Sub

 

 

The type and location of client instance certificate store can be controlled by properties in EasyUAApplication.ApplicationParameters.ApplicationManifest, such as the InstanceOwnStorePath Property. By default, QuickOPC-UA uses a standard directory-based store defined by OPC Foundation (“MachineDefault”).

The AllowUserInteraction Property of the EasyUAApplication.ApplicationParameters.InstanceCertificateGenerationParameters determines whether the component can interact with the user when checking or creating an application instance certificate. If set to false, no dialogs will be displayed.

Instance Certificate Auto-Generation

QuickOPC will automatically generate the application instance certificate if one is not found, and the AutoGenerateInstanceCertificate Property is true (which is the default setting).

The auto-generation of client instance certificate is skipped when the effective endpoint selection policy only allows connections with no message security.

If you let QuickOPC-UA create the certificate and add it to the store, it should be noted that it is a security-sensitive operation that would typically be allowed only to administrators. QuickOPC-UA will attempt to do this if the certificate is not found, which may be when the application is first started on the computer, but if your application is not running with privileges required for this operation, the certificate will not be added.

In order to allow your application be run under usual privileges, and make its behavior more predictable, it is recommended that you assure the generation of the certificate during the application deployment, when administrative privileges are usually required anyway. One way to do this is call the static method EasyUAClient.Install during the deployment process.  For more information, see the “Application Deployment” chapter.

The default validity period of the auto-generated certificate is 60 months (5 years). The default key size of the auto-generated certificates is determined by the OPC UA stack, and is currently 2048 bits.

The auto-generated certificate lifetime, and its key size, can be influenced by parameters in the EasyUAClient.SharedParameters.EngineParameters.InstanceCertificateGenerationParameters Property, which contains an instance of CertificateGenerationParameters Class.

The minimum key size of the generated certificate (in bits) is given by the MinimumKeySize Property. The underlying generation certificate mechanism will choose a key size that is greater or equal to the value of this property. The default value of this property, which is zero, causes the certificate generation mechanism to choose its default key size.

The lifetime of the generated certificate (always expressed in whole moths) is given by a combination of two properties: The MaximumExpirationDate Property and the ValidityPeriodInMonths Property. Whichever property yields a shorter lifetime (in months), wins. By default, the MaximumExpirationDate Property is set to a maximum valid date, and the ValidityPeriodInMonths Property is set to 60 months (5 years).

Use caution when choosing long certificate lifetimes, possibly in hope of preventing hassles with certificate renewal. Not only the long certificate lifetime may not be secure enough, but some systems your application runs on or communicates with (other OPC UA party - usually a server) may have problems processing dates that are too far into the future. See e.g. Year 2038 problem .
// This example show how to set the validity period of the application instance certificate.

using System;
using OpcLabs.BaseLib.Security.Cryptography.PkiCertificates;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.Application;
using OpcLabs.EasyOpc.UA.Application.Extensions;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._CertificateGenerationParameters
{
    class ValidityPeriodInMonths
    {
        public static void Main1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            Console.WriteLine("Setting the validity period of the auto-generated instance certificate to 50 years (600 months)...");
            EasyUAApplication.Instance.ApplicationParameters.InstanceCertificateGenerationParameters.ValidityPeriodInMonths = 600;

            Console.WriteLine("Obtaining the application interface...");
            var client = new EasyUAClient();
            EasyUAApplication application = EasyUAApplication.Instance;

            try
            {
                Console.WriteLine("Removing the current application instance certificate...");
                application.RemoveOwnCertificate(mustExist:false);

                Console.WriteLine("Do something - invoke an OPC read, to trigger auto-generation of a new instance certificate...");
                client.ReadValue(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853");

                Console.WriteLine("Finding the current application instance certificate...");
                IPkiCertificate instanceCertificate = application.FindOwnCertificate();

                if (!(instanceCertificate is null))
                    Console.WriteLine($"Expiration date: {instanceCertificate.NotAfter}");
            }
            catch (UAException uaException)
            {
                Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}");
            }
        }
    }
}
# This example show how to set the validity period of the application instance certificate.

# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.Application import *
from OpcLabs.EasyOpc.UA.Application.Extensions import *
from OpcLabs.EasyOpc.UA.OperationModel import *


endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
    # or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
    # or 'https://opcua.demo-this.com:51212/UA/SampleServer/'

print('Setting the validity period of the auto-generated instance certificate to 50 years (600 months)...')
EasyUAApplication.Instance.ApplicationParameters.InstanceCertificateGenerationParameters.ValidityPeriodInMonths = 600

print('Obtaining the application interface...')
client = EasyUAClient()
application = EasyUAApplication.Instance

try:
    print('Removing the current application instance certificate...')
    IEasyUAClientServerApplicationExtension.RemoveOwnCertificate(application, False) # mustExist=False

    print('Do something - invoke an OPC read, to trigger auto-generation of a new instance certificate...')
    IEasyUAClientExtension.ReadValue(client,
                                     endpointDescriptor, UANodeDescriptor("nsu=http://test.org/UA/Data/ ;i=10853"))

    print('Finding the current application instance certificate...')
    instanceCertificate = IEasyUAClientServerApplicationExtension.FindOwnCertificate(application)

    if instanceCertificate is not None:
        print('Expiration date: ', instanceCertificate.NotAfter, sep='')
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

print('Finished.')

 

If you do not like the parameters of the auto-generated certificate, you can also create your own certificate and place it into the appropriate certificate store(s). As long as the certificate has the proper Subject Name, it will be found by QuickOPC and used.

When using the EasyUAClient.Install method during the deployment process, make sure that the application (certificate) name is the same during deployment, and during the normal application. With automatically generated application name (which is the default), a different name might be generated if you use a separate application for the deployment, or if use you use utilities such as InstallUtil.exe which effectively act as a host for your application. In such situations, always set the application name explicitly, to the same value during the deployment and in normal application executions.

QuickOPC attempts to re-generate the own instance certificate whenever it is needed and not found. You can therefore enforce re-creation of the instance certificate (e.g. periodically, in order to prevents its expiration) by simply removing it from the appropriate certificate store (e.g. by a script called from Windows Task Scheduler). Note that when the instance certificate is replaced, the other parties (communication peers) will most likely no longer trust the certificate, and the trust will have to be reestablished on their side.

Peer Auto-Trust

When QuickOPC creates or checks the client instance certificate (in the application certificate store), it also makes sure that the certificate is to be found in the trusted peers certificate store ("UA Applications", normally). If the client instance certificate store is not found there, a copy of it (without the private key) is placed into the trusted peers certificate store automatically.

With this peer auto-trust mechanism, OPC UA servers that use the same trusted peers certificate store can automatically trust the client application(s) created with QuickOPC.

Whether the auto-generated client instance certificate will be also placed into the trusted peers certificate store can be controlled using the AutoTrustInstanceCertificate Property.

QuickOPC applications also check the trust status of their own application instance certificate using basically the same mechanism as other applications. For this reason, the peer-auto trust is actually needed not just for the peer application, but also for proper function of the QuickOPC application itself. A copy (without the private key) of the application instance certificate should also always exist in the trusted peers certificate store.
With the default settings effective when targeting .NET 6+, applications use separate certificate stores and not system-wide "shared" certificate stores. The peer auto-trust mechanism is still invoked under .NET 6+, but with the default settings it may have no observable effect, because other applications are using different certificate stores.

Application Instance Certificate Validation

If the ValidateOwnInstanceCertificate Property is true, and the application instance certificate is found in the appropriate certificate store, QuickOPC validates the certificate. If any checks fails, and instance certificate auto-generation is turned on (which is by default - see above), QuickOPC creates a new certificate and replaces the certificate in the store.

  1. The certificate must be valid.
  2. The size of the certificate's public key must be at least the minimum size. Currently, QuickOPC uses zero as minimum size, therefore all certificates pass this check.
  3. If the application type includes a Server, the certificate's domains are checked against the server configuration. QuickOPC applications are normally client-only (unless you specify otherwise), and therefore this check always passes in the default QuickOPC configuration.
  4. The application URI must be specified (non-empty) in the certificate. The application URI is an URI from the certificate extension with OID 2.5.29.7 (subjectAltName) or 2.5.29.17 (Subject Alternative Name).
By the quirk in the checking algorithm, the client application certificate must also be trusted, which can be assured by placing a copy of it (without private key) into the trusted peers certificate store ("UA Applications", normally). The certificate auto-creation in QuickOPC does this automatically, but do not forget about this step when generating and placing your application certificate manually.

For OPC compliance, the application instance certificate validation must be turned on.

Additional information

OPC-UA requires that both parties (client and server) mutually identify themselves using application certificates. The certificates are supposed to be unique for each application (instance), and therefore cannot be a constant part of the "toolkit" (such as QuickOPC), and need to be generated. In order to make this process invisible (in common cases) to the developer, QuickOPC

a) determines the parameters of the certificate automatically, using values such as the EXE name or the calling assembly name,

b) attempts to look up the certificate in the certificate store,

c) if not found, it attempts to create it, and save it into the certificate store. 

The algorithm described above does not, however, fit well with hosted environments such as IIS, for two reasons:

For usage in such environments, the recommendation is:

On Windows, application certificate can be manually generated using Opc.Ua.CertificateGenerator.exe utility, available (in source code) from the OPC Foundation GitHub. If you have used some older OPC UA software, the utility might be installed on your system, and is typically located at "C:\Program Files (x86)\Common Files\OPC Foundation\UA\v1.0\Bin". If you do not have it on your system, you can download our build of it from our Knowledge Base: Tool Downloads (UA Certificate Generator) . Run the tool with "/?" on the command line to obtain usage instructions. See also Certificate Generator page.

Setting the certificate parameters is done by modifying properties in EasyUAClient.SharedParameters.EngineParameters.ApplicationParameters (EasyUAClient.SharedParameteres is a static property, and you are advised to set the values before creating the first instance of EasyUAClient, in order for it to always have the desired effect for certificate auto-generation). The properties of interest are:

The values should match those used when the certificate was generated, because they (or at least some of them) are used to look up the certificate in the store.

The application URI can be set to a specific value, or (when not set, which is the default), QuickOPC will use the application URI template string to make an application URI. For the template syntax, and more details about how application URI is determined, see OPC UA Application URI Derivation.

QuickOPC also includes the UA Configuration Tool in the Bonus Material part of its full installation for Windows. You can access the UA Configuration Tool from the Start menu (under QuickOPC program group), or using the QuickOPC Launcher application.

You should not use the same certificate for multiple applications. And, you should not use the same certificate even for multiple instances of the same application (such as when you deploy the application on multiple computers). Each instance of the application (typically, this means each application/computer combination, but can be even more granular) should have its own, unique certificate. This is how UA security is meant to work, because there needs to be a way for the server to authenticate each client connection separately and possibly deny the connection to unsecure or compromised clients. Technically, if you violate this and use the same certificate, things will probably work OK on the surface and initially, but it is against the OPC-UA security specs. This is the reason why the certificate is generated anew on the computer - and also the cause of some troubles.

Actually, while generating the certificates manually is possible, it would be probably too complicated to try to assemble the right set of parameters so that the generated certificate is then properly found by the client application. Instead, we suggest that you create a small app (e.g. Windows Forms app, or a console app). In it, you set the 4 parameters in EasyUAClient.SharedParameters to meaningful values, and then call a static method EasyUAClient.Install(). You then run this application with administrator/elevated privileges, and it will create the certificate (verify it with the UA Configuration Tool described above). In your actual client app, set the parameters in precisely the same way before instantiating the EasyUAClient object, and doing so should assure that it will find and use the certificate. Still, your app (which may be a Web app) needs to have read access to the directory of the cert store - you may have to modify the permissions). The additional app you created may become part of your installation procedure.

Multiple Application Instance Certificates

In advanced scenarios, an OPC UA application may use multiple application instance certificates, with the help of so-called certificate sub-ids. For more information on this subject, see OPC UA Client-Server Application Service.

Private Key Password

It is possible to protect the private key of the client instance certificate with a password. The password can be set using the UAClientServerApplicationParameters.InstanceCertificatePrivateKeyPassword Property. The same password setting is used when accessing an existing private key, or when a new certificate is generated (together with its private key).

In addition, the relevant operations on the IEasyUAClientServerApplication interface (see OPC UA Client-Server Application Service) also have an additional argument for the private key password.

You can also password-protect or unprotect the private key of an existing certificate. The corresponding methods (and extension methods) on the IEasyUAClientServerApplication Interface are: ProtectOrUnprotectOwnCertificate, ProtectOwnCertificate, and UnprotectOwnCertificate.

You are responsible for providing and/or persisting the private key password. That is, if you simply protect the certificate with the password, without further actions, the next time the application runs, it will not know what the pasword was. Extra code is needed to make sure the proper password is used each time the application is run. For example, a fixed password might be hard-coded in your program. This approach works, but you need to be aware that the password can be extracted from the program if the attacker gains access to it, and that hard-coding the password also makes it difficult to change it. More sophisticated solutions will e.g. persist the password in some kind of a secure storage area.

Obtaining Instance Certificate from the GDS 

If your OPC UA setup includes an OPC UA Global Registration Server (GDS), you might be able to obtain the application instance certificate from the GDS (in the role of Certificate Manager, CM). For more information, see OPC UA Client-Server Application Service (or, less preferrably, OPC UA Certificate Management Client).

Troubleshooting

Some common problem scenarios include:

Certificate generation works on one computer, does not on other. For example, when you first run your application your development computer, you may use the development Web server built-in in Visual Studio. This one uses different accounts and permissions from IIS, and the certificate creates just fine. On the production computer, IIS is used, and the certificate generation may fail. See further below for related information.

Certificate generation fails under IIS. Most likely this is due to permissions. IIS settings are VERY restrictive (for good reason), and the defaults won't allow the certification generation or storing it into the store.  

See Also

Examples - OPC UA GDS and CM

Examples - OPC UA Application

Knowledge Base