1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtopcua-security.html
\title Creating OPC UA Clients with security support
\brief Instructions how to create OPC UA Clients with security support
One of the core features of OPC UA is the support for security,
which means we get cryptographically encrypted and signed protocol,
user authentication and authorization support.
To make this work, each application instances (installation of a program)
needs to have its own \c {Application Instance Certificate} and the according private key.
The applications can either generate self-signed certificates on their own, get some from a
certificate authority using OPC UA GDS, or simply can be configured with certificates which
haven been created manually by the user.
Because at the moment Qt OPC UA does not support certificate generation or GDS,
this tutorial describes how to generate a self-signed OPC UA certificate on the command line
using OpenSSL.
\section2 Create a new Application Certificate
To be able to generate a correct x509v3 certificate with all required extensions for OPC UA,
we need to setup a configuration file with all the necessary information first.
Remember to change \c subject and \c subjectAltName to match your case.
It is important to insert the \c ApplicationURI of the application into the \c URI field of \c subjectAltName,
and that the hostname of your PC or device is inserted in the \c DNS fields of \c subjectAltName.
Alternatively, you can use \c IP field if your device does not support host names and you are working
with static IPs.
Future versions of Qt OPC UA will be able to generate the certificate for you with correct information.
For now, you can create one using the OpenSSL command line tool.
Example: \c opcuaviewer.config
\code
[ req ]
default_bits = 2048
default_md = sha256
distinguished_name = subject
req_extensions = req_ext
x509_extensions = req_ext
string_mask = utf8only
prompt = no
[ req_ext ]
basicConstraints = critical, CA:FALSE
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = URI:urn:foo.com:The%20Qt%20Company:QtOpcUaViewer,DNS:foo.com
subjectKeyIdentifier = hash
authorityKeyIdentifier=keyid:always,issuer:always
[ subject ]
countryName = DE
stateOrProvinceName = Berlin
localityName = Berlin
organizationName = The Qt Company
commonName = QtOpcUaViewer
\endcode
Using this configuration file, OpenSSL is able to create a matching certificate for local use.
\code
# create a self-signed certificate and private key
openssl req -new -x509 -config opcuaviewer.config -newkey rsa:2048 -keyout opcuaviewer.key -nodes -outform der -out opcuaviewer.der
# install the certificate and key into the application PKI directory
mv opcuaviewer.der /path/to/application/pki/own/certs/opcuaviewer.der
mv opcuaviewer.key /path/to/application/pki/own/private/opcuaviewer.pem
# secure private key file permissions
chmod 600 /path/to/application/pki/own/private/opcuaviewer.pem
\endcode
It is important to secure the file permission of the private key, so that only the UA application can read it.
For services (daemons), it is recommended to create dedicated unprivileged users accounts for this and make this
user the owner of the key. For interactive applications, this key should be individual to the user.
For interactive applications, it is also possible to password protect the key. In this case, the user needs to enter
the password every time the application is started and loading the key.
For this reason, password protected keys are not a good solution for unattended applications, because this would
required to store the password in a configuration file.
You can dump the certificate data using OpenSSL to inspect the contents of the certificate:
\code
openssl x509 -in opcuaviewer.der -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
be:aa:41:79:8a:b0:4f:9a
Signature Algorithm: sha512WithRSAEncryption
Issuer: C = DE, ST = Berlin, L = Berlin, O = The Qt Company, CN = QtOpcUaViewer
Validity
Not Before: Nov 7 14:38:52 2018 GMT
Not After : Dec 7 14:38:52 2018 GMT
Subject: C = DE, ST = Berlin, L = Berlin, O = The Qt Company, CN = QtOpcUaViewer
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
[ skipped ]
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Certificate Sign
X509v3 Subject Alternative Name:
URI:urn:foo.com:The%20Qt%20Company:QtOpcUaViewer, DNS:foo.com
X509v3 Subject Key Identifier:
B2:E8:5E:34:21:EA:67:CF:61:FC:14:94:18:C1:AD:13:89:83:CA:9B
X509v3 Authority Key Identifier:
keyid:B2:E8:5E:34:21:EA:67:CF:61:FC:14:94:18:C1:AD:13:89:83:CA:9B
DirName:/C=DE/ST=Berlin/L=Berlin/O=The Qt Company/CN=QtOpcUaViewer
serial:BE:AA:41:79:8A:B0:4F:9A
Signature Algorithm: sha512WithRSAEncryption
[ skipped ]
\endcode
\section2 Configuring the UA Application
To make security working with the certificate created in the previous step, it is important to
\list
\li Configure the correct Application Identity
\snippet ../../examples/opcua/opcuaviewer/mainwindow.cpp Application Identity
\li Configure PKI locations so that the SDK can find the certificate, private key, trust list etc.
\snippet ../../examples/opcua/opcuaviewer/mainwindow.cpp PKI Configuration
\endlist
\section2 PKI Folder Layout
Qt OPC UA uses the following folder layout:
\table
\header
\li Folder
\li Description
\row
\li own
\li Location to store the application's own certificates.
\row
\li trusted
\li A list of trusted application certificates or trusted CA certificates.
\row
\li issuer
\li A list of certificates for CAs which are not trusted but are needed to
check signatures on certificates.
\row
\li rejected
\li Here the application stores rejected certificates, so that they can later on be trusted by an Administrator.
It is important to have a configured maximum number of files here. If this is reached, the oldest
file should be deleted first. Without a limit, an attacker could fill the machine's hard disk with
invalid connection attempts.
\endtable
Each of the folders \c own, \c trusted, and \c issuers contain the subdirectory structure defined by the following table.
\table
\header
\li Subdirectory
\li Description
\row
\li certs
\li Contains the DER encoded X.509 v3 certificates. The files shall have a .der file extension.
\row
\li private
\li Contains the private keys. The format of the file may be backend specific.
PEM encoded files should have a .pem extension. PKCS#12 encoded files should have a .pfx extension.
The root file name shall be the same as the corresponding public key file in the certs directory.
This folder only exists inside the \c own folder.
\row
\li crl
\li Contains the DER encoded CRL for any CA certificates found in the certs directories.
The files shall have a .crl file extension.
\endtable
\section2 First connection
When connecting for the first time, the client needs to trust the server certificate.
The client should display a certificate warning (with cert details) and offer the possibility to save the certificate in its trust list.
For an example, see \l{Qt OPC UA Viewer Example}.
When the client has accepted the server certificate, you can try to connect again. Now the server may reject the client's certificate.
This is indicated by the generic error code \c BadSecurityChecksFailed. Server normally store rejected certificates in a special \c rejected folder.
Administrator can move these into the trust list to trust clients. This avoids manually copying the client certificate to the server machine.
As soon as the server has trusted the client, you should be able to connect with security.
*/
|