Erstellen von OPC UA Clients mit Sicherheitsunterstützung

Eines der Hauptmerkmale von OPC UA ist die Unterstützung von Sicherheit, was bedeutet, dass wir ein kryptografisch verschlüsseltes und signiertes Protokoll, Benutzerauthentifizierung und Autorisierungsunterstützung erhalten.

Damit dies funktioniert, muss jede Anwendungsinstanz (Installation eines Programms) ihre eigene Application Instance Certificate und den entsprechenden privaten Schlüssel haben.

Die Anwendungen können entweder selbst signierte Zertifikate generieren, einige von einer Zertifizierungsstelle unter Verwendung von OPC UA GDS erhalten oder einfach mit Zertifikaten konfiguriert werden, die vom Benutzer manuell erstellt wurden.

Da Qt OPC UA zur Zeit weder Zertifikatsgenerierung noch GDS unterstützt, wird in diesem Tutorial beschrieben, wie man ein selbstsigniertes OPC UA Zertifikat auf der Kommandozeile mit OpenSSL generiert.

Erstellen Sie ein neues Anwendungszertifikat

Um ein korrektes x509v3 Zertifikat mit allen erforderlichen Erweiterungen für OPC UA erzeugen zu können, müssen wir zunächst eine Konfigurationsdatei mit allen notwendigen Informationen erstellen.

Denken Sie daran, subject und subjectAltName entsprechend Ihrem Fall zu ändern.

Es ist wichtig, dass Sie die ApplicationURI der Anwendung in das URI Feld von subjectAltName einfügen, und dass der Hostname Ihres PCs oder Geräts in das DNS Feld von subjectAltName eingefügt wird. Alternativ können Sie das IP Feld verwenden, wenn Ihr Gerät keine Hostnamen unterstützt und Sie mit statischen IPs arbeiten. Zukünftige Versionen von Qt OPC UA werden in der Lage sein, das Zertifikat mit den korrekten Informationen für Sie zu generieren. Im Moment können Sie es mit dem OpenSSL-Befehlszeilentool erstellen.

Beispiel: opcuaviewer.config

[ 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, dataEncipherment
extendedKeyUsage = clientAuth
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

Mit dieser Konfigurationsdatei ist OpenSSL in der Lage, ein passendes Zertifikat für die lokale Verwendung zu erstellen.

# 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

Es ist wichtig, die Dateiberechtigung des privaten Schlüssels so zu sichern, dass nur die UA-Anwendung ihn lesen kann. Für Dienste (Daemons) empfiehlt es sich, dafür eigene unprivilegierte Benutzerkonten anzulegen und diesen Benutzer zum Eigentümer des Schlüssels zu machen. Bei interaktiven Anwendungen sollte dieser Schlüssel individuell für den Benutzer sein. Bei interaktiven Anwendungen ist es auch möglich, den Schlüssel mit einem Passwort zu schützen. In diesem Fall muss der Benutzer das Kennwort jedes Mal eingeben, wenn die Anwendung gestartet wird und der Schlüssel geladen wird. Aus diesem Grund sind passwortgeschützte Schlüssel keine gute Lösung für unbeaufsichtigte Anwendungen, da in diesem Fall das Passwort in einer Konfigurationsdatei gespeichert werden müsste.

Sie können die Zertifikatsdaten mit OpenSSL auslesen, um den Inhalt des Zertifikats zu untersuchen:

        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 ]

Konfigurieren der UA-Anwendung

Damit die Sicherheit mit dem im vorherigen Schritt erstellten Zertifikat funktioniert, ist es wichtig, dass

  • Konfigurieren Sie die richtige Anwendungsidentität
    m_identity = m_pkiConfig.applicationIdentity();
  • Konfigurieren Sie die PKI-Speicherorte, damit das SDK das Zertifikat, den privaten Schlüssel, die Vertrauensliste usw. finden kann.

    Siehe z. B. den Code aus dem Qt OPC UA Viewer-Beispiel:

    void MainWindow::setupPkiConfiguration() { const QDir pkidir =QDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/pki"); if (!pkidir.exists() && !copyDirRecursively(":/pki", pkidir.path()))        qFatal("Could not set up directory %s!", qUtf8Printable(pkidir.path()));
    
        m_pkiConfig.setClientCertificateFile(pkidir.absoluteFilePath("own/certs/opcuaviewer.der")); m_pkiConfig.setPrivateKeyFile(pkidir.absoluteFilePath("own/private/opcuaviewer.pem")); m_pkiConfig.setTrustListDirectory(pkidir.absoluteFilePath("trusted/certs")); m_pkiConfig.setRevocationListDirectory(pkidir.absoluteFilePath("trusted/crl")); m_pkiConfig.setIssuerListDirectory(pkidir.absoluteFilePath("issuers/certs")); m_pkiConfig.setIssuerRevocationListDirectory(pkidir.absoluteFilePath("issuers/crl")); const QStringList toCreate = { m_pkiConfig.issuerListDirectory(),m_pkiConfig.issuerRevocationListDirectory() }; for(const QString &dir: toCreate) { if (!QDir().mkpath(dir))            qFatal("Could not create directory %s!", qUtf8Printable(dir));
        } }

    Im Beispiel extrahieren wir vorkonfigurierte eigene und vertrauenswürdige Zertifikate aus dem Qt-Ressourcensystem an einen beschreibbaren Ort im Dateisystem. Die übrigen Verzeichnisse für Aussteller-(Sperr-)Listen werden manuell erstellt.

PKI-Ordner-Layout

Qt OPC UA verwendet das folgende Ordnerlayout:

OrdnerBeschreibung
eigeneOrt, an dem die eigenen Zertifikate der Anwendung gespeichert werden.
vertrauenswürdigEine Liste von vertrauenswürdigen Anwendungszertifikaten oder vertrauenswürdigen CA-Zertifikaten.
ausstellerEine Liste von Zertifikaten für CAs, die nicht vertrauenswürdig sind, aber zur Überprüfung von Signaturen auf Zertifikaten benötigt werden.
abgelehntHier speichert die Anwendung abgelehnte Zertifikate, so dass sie später von einem Administrator als vertrauenswürdig eingestuft werden können. Es ist wichtig, dass hier eine maximale Anzahl von Dateien konfiguriert ist. Wenn diese erreicht ist, sollte die älteste Datei zuerst gelöscht werden. Ohne ein Limit könnte ein Angreifer die Festplatte des Rechners mit ungültigen Verbindungsversuchen füllen.

Jeder der Ordner own, trusted und issuers enthält die in der folgenden Tabelle definierte Unterverzeichnisstruktur.

UnterverzeichnisBeschreibung
certsEnthält die DER-kodierten X.509 v3-Zertifikate. Die Dateien müssen eine .der-Dateierweiterung haben.
privatEnthält die privaten Schlüssel. Das Format der Datei kann backendspezifisch sein. PEM-kodierte Dateien sollten eine .pem-Erweiterung haben. PKCS#12-kodierte Dateien sollten die Endung .pfx haben. Der Name der Stammdatei muss mit dem Namen der entsprechenden öffentlichen Schlüsseldatei im certs-Verzeichnis übereinstimmen. Dieser Ordner existiert nur innerhalb des Ordners own.
crlEnthält die DER-kodierte CRL für alle CA-Zertifikate, die sich in den certs-Verzeichnissen befinden. Die Dateien müssen eine .crl-Dateierweiterung haben.

Erste Verbindung

Bei der ersten Verbindung muss der Client dem Serverzertifikat vertrauen.

Der Client sollte eine Zertifikatswarnung (mit Zertifikatsdetails) anzeigen und die Möglichkeit bieten, das Zertifikat in seiner Vertrauensliste zu speichern. Ein Beispiel finden Sie unter Qt OPC UA Viewer Example.

Wenn der Client das Serverzertifikat akzeptiert hat, können Sie erneut versuchen, eine Verbindung herzustellen. Nun kann es sein, dass der Server das Zertifikat des Clients ablehnt. Dies wird durch den generischen Fehlercode BadSecurityChecksFailed angezeigt. Server speichern abgelehnte Zertifikate normalerweise in einem speziellen Ordner rejected. Der Administrator kann diese in die Vertrauensliste verschieben, um den Clients zu vertrauen. Dies erspart das manuelle Kopieren des Client-Zertifikats auf den Server.

Sobald der Server dem Client vertraut hat, sollten Sie eine sichere Verbindung herstellen können.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.