Skip to content
Start free evaluation

PKI and trust setup

  • Create application instance certificates and private keys for a server and a client.
  • Check that the certificates carry the extensions OPC UA needs.
  • See how a connection behaves when each side trusts the other, and when it doesn’t.
  • Steps 1 to 3 of the lab setup: unpacked packages and the environment variables.
  • The OpenSSL 3 command-line tool.

The SDK ships two OpenSSL configuration templates in examples/opcua/pki:

examples/opcua/pki/server.cnf
# Self-signed OPC UA application instance certificate for the example server.
# Change the URI to your server ApplicationUri and the DNS/IP names to the host
# names used in the endpoint URL.
[req]
prompt = no
distinguished_name = subject
x509_extensions = application
[subject]
CN = PDComm OPC UA Example Server
O = Example Organization
[application]
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = URI:urn:pdcomm:opcua:server, DNS:localhost, IP:127.0.0.1
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
examples/opcua/pki/client.cnf
# Self-signed OPC UA application instance certificate for the example client.
# The URI must equal the client ApplicationUri (default urn:pdcomm:opcua:client).
[req]
prompt = no
distinguished_name = subject
x509_extensions = application
[subject]
CN = PDComm OPC UA Example Client
O = Example Organization
[application]
basicConstraints = critical, CA:FALSE
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = URI:urn:pdcomm:opcua:client, DNS:localhost
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
Setting Meaning
CN, O The subject name. PDComm rejects a certificate where either is empty.
basicConstraints = critical, CA:FALSE An application certificate, not a certificate authority.
keyUsage The key usages OPC UA requires; keyCertSign is there because the certificate is self-signed.
extendedKeyUsage Server authentication (serverAuth) and client authentication (clientAuth)
subjectAltName URI: is the ApplicationUri; DNS: and IP: are the host names and addresses clients use to reach the server.

A client checks that the host in the endpoint URL matches a DNS: or IP: entry of the server certificate. The template contains only localhost and 127.0.0.1. If clients will reach the server from another computer or by its computer name, add that name.

Find the computer name:

터미널 창
hostname

Add the name to the subjectAltName line of $PKI/server.cnf. This tutorial assumes the computer is called my-pc; use your real name instead.

subjectAltName = URI:urn:pdcomm:opcua:server, DNS:localhost, DNS:my-pc, IP:127.0.0.1

Some Windows clients replace localhost in the endpoint URL with the computer name before they connect. If the server runs on Windows, or Windows clients connect to it, always include the computer name. Certificate problems explains why.

터미널 창
cd "$PKI"
openssl req -x509 -new -config server.cnf -newkey rsa:2048 -sha256 -days 365 -noenc \
-keyout server.key.pem -out server.cert.pem
openssl x509 -in server.cert.pem -outform DER -out server.der
openssl req -x509 -new -config client.cnf -newkey rsa:2048 -sha256 -days 365 -noenc \
-keyout client.key.pem -out client.cert.pem
openssl x509 -in client.cert.pem -outform DER -out client.der
chmod 600 server.key.pem client.key.pem
ls -1

Result:

client.cert.pem
client.cnf
client.der
client.key.pem
server.cert.pem
server.cnf
server.der
server.key.pem

What each file is for:

File Format Used by
server.der DER certificate The server’s identity; also the certificate the client trusts
server.key.pem PEM private key Read by the server only
server.cert.pem PEM certificate The identity file of a simulator server
client.der DER certificate The client’s identity; also the certificate the server trusts
client.key.pem PEM private key Read by the client only
client.cert.pem PEM certificate The identity file of a simulator client

The SDK takes certificates as DER and private keys as PEM, each up to 64 KiB. The simulator reads both DER and PEM.

Check the server certificate’s subject and extensions:

터미널 창
openssl x509 -in server.cert.pem -noout -subject -ext subjectAltName,keyUsage,extendedKeyUsage
subject=CN=PDComm OPC UA Example Server, O=Example Organization
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Certificate Sign
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Subject Alternative Name:
URI:urn:pdcomm:opcua:server, DNS:localhost, DNS:my-pc, IP Address:127.0.0.1

Check the validity period too. The template commands create certificates valid for one year.

터미널 창
openssl x509 -in server.cert.pem -noout -dates
notBefore=Oct 14 16:56:03 2026 GMT
notAfter=Oct 14 16:56:03 2027 GMT

If you haven’t built the examples yet, run step 5 of the lab setup first. In a first terminal, start the server, which trusts only client.der:

터미널 창
cd "$OPCUA_SDK"
build/opcua_server 127.0.0.1:4840 opc.tcp://localhost:4840/pdcomm "$PKI/server.der" "$PKI/server.key.pem" "$PKI/client.der"

In a second terminal, run the client, which trusts only server.der:

터미널 창
cd "$OPCUA_SDK"
build/opcua_client opc.tcp://localhost:4840/pdcomm "$PKI/client.der" "$PKI/client.key.pem" "$PKI/server.der"

When these lines follow the endpoint list, each side trusted the other:

Session activated (anonymous)
Read ns=2;i=1001 value=42 service=0x00000000 status=0x00000000
Session closed

The connection also works with 127.0.0.1 as the URL host, because the server certificate contains IP:127.0.0.1.

Create one more certificate that nobody trusts:

터미널 창
cd "$PKI"
openssl req -x509 -new -config client.cnf -newkey rsa:2048 -sha256 -days 365 -noenc \
-keyout other.key.pem -out other.cert.pem
openssl x509 -in other.cert.pem -outform DER -out other.der
chmod 600 other.key.pem
cd "$OPCUA_SDK"

The client doesn’t trust the server. Pass other.der as the server certificate to trust:

터미널 창
build/opcua_client opc.tcp://localhost:4840/pdcomm "$PKI/client.der" "$PKI/client.key.pem" "$PKI/other.der"
Error: connect failed (SDK status 5): OPC UA security CertificateUntrusted

The client rejected the server certificate itself, so you see the error’s name. The exit code is 3.

The server doesn’t trust the client. Use other.der and other.key.pem as the client identity:

터미널 창
build/opcua_client opc.tcp://localhost:4840/pdcomm "$PKI/other.der" "$PKI/other.key.pem" "$PKI/server.der"
Error: connect failed (SDK status 5): OPC UA status: 0x80130000

0x80130000 is BadSecurityChecksFailed. For security, the server doesn’t tell the client why it refused; when you see this error, check the server’s trust settings first.

The certificate and private key don’t belong together:

터미널 창
build/opcua_client opc.tcp://localhost:4840/pdcomm "$PKI/client.der" "$PKI/other.key.pem" "$PKI/server.der"
Error: connect failed (SDK status 5): OPC UA security InvalidKey
  • Make private key files readable only by the account that runs the application (chmod 600).
  • Keep private keys out of packages, repositories and logs. The PDComm SDK and examples never print keys or passwords.
  • The SDK copies the key when it connects. Wipe your own key buffer right after connecting, as example_wipe in the examples does.
  • Renew certificates before they expire, and update the peer’s trust settings to the new certificate.

Press Ctrl+C in the server’s terminal, then delete the test certificate:

터미널 창
rm "$PKI"/other.*

Keep server.* and client.*; the other tutorials use them.