セキュリティ対応OPC UAクライアントの作成

OPC UAのコア機能の1つは、セキュリティのサポートです。つまり、暗号化され署名されたプロトコル、ユーザー認証、認可がサポートされています。

この機能を実現するためには、各アプリケーション・インスタンス(プログラムのインストール)が独自のApplication Instance Certificate 、それに応じた秘密鍵を持つ必要があります。

アプリケーションは、自分で自己署名証明書を生成することも、OPC UA GDSを使用して認証局から証明書を取得することも、ユーザーが手動で作成した証明書で構成することもできます。

現時点では、Qt OPC UA は証明書の生成や GDS をサポートしていないため、このチュートリアルでは、OpenSSL を使用してコマンドラインで自己署名の OPC UA 証明書を生成する方法を説明します。

新しいアプリケーション証明書の作成

OPC UA に必要なすべての拡張子を持つ正しい x509v3 証明書を生成できるようにするには、まず必要なすべての情報を含む設定ファイルをセットアップする必要があります。

subjectsubjectAltName をケースに合わせて変更することを忘れないでください。

subjectAltNameURI フィールドにアプリケーションのApplicationURI を挿入し、subjectAltNameDNS フィールドに PC またはデバイスのホスト名を挿入することが重要です。また、デバイスがホスト名をサポートしておらず、静的 IP を使用している場合は、IP フィールドを使用することもできます。Qt OPC UA の将来のバージョンでは、正しい情報で証明書を生成できるようになる予定です。今のところ、OpenSSLのコマンドラインツールを使って証明書を作成することができます。

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

このコンフィギュレーション・ファイルを使って、OpenSSLはローカル用の証明書を作成することができます。

# 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

秘密鍵のファイルパーミッションを確保して、UAアプリケーションだけがそれを読めるようにすることが重要である。サービス(デーモン)の場合、このために専用の非特権ユーザーアカウントを作成し、このユーザーを鍵の所有者にすることを推奨する。対話型アプリケーションの場合、この鍵はユーザーごとに持つべきである。対話型アプリケーションの場合、鍵をパスワードで保護することも可能である。この場合、ユーザーはアプリケーションを起動し、キーをロードするたびにパスワードを入力する必要がある。このような理由から、パスワードで保護されたキーは、無人のアプリケーションにとっては良い解決策ではありません。

OpenSSL を使用して証明書データをダンプし、証明書の内容を検査することができます:

        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 ]

UAアプリケーションの設定

前の手順で作成した証明書でセキュリティを動作させるには、以下のことが重要である。

  • 正しいアプリケーションIDを構成する
    m_identity = m_pkiConfig.applicationIdentity();
  • SDKが証明書、秘密鍵、トラストリストなどを見つけられるように、PKIロケーションを構成する。

    例えば、Qt OPC UA Viewer Example のコードを参照:

    voidMainWindow::setupPkiConfiguration() {constQDirpkidir=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"));constQStringListtoCreate={ m_pkiConfig.issuerListDirectory(),m_pkiConfig.issuerRevocationListDirectory() };for(constQString&dir: toCreate) {if(QDir().mkpath(dir))            qFatal("Could not create directory %s!", qUtf8Printable(dir));
        } }

    この例では、Qtリソースシステムから、事前に設定された自己証明書と信頼済み証明書をファイルシステム内の書き込み可能な場所に展開します。残りの発行者(失効)リスト用のディレクトリは手動で作成します。

PKI フォルダのレイアウト

Qt OPC UA では、以下のフォルダ・レイアウトを使用します:

フォルダ説明
自身のアプリケーション自身の証明書を格納する場所。
trusted信頼できるアプリケーション証明書または信頼できるCA証明書のリスト。
発行者信頼されていないが、証明書の署名をチェックするために必要なCAの証明書のリスト。
拒否ここでアプリケーションは拒否された証明書を保存し、後に管理者が信頼できるようにする。ここにファイルの最大数を設定することが重要である。この数に達した場合、最も古いファイルから削除される。制限を設けないと、攻撃者がマシンのハード・ディスクを無効な接続試行で一杯にする可能性がある。

owntrustedissuers の各フォルダには、以下の表で定義されるサブディレクトリ構造が含まれる。

サブディレクトリ説明
certsDER エンコードされた X.509 v3 証明書が格納される。ファイルの拡張子は .der とする。
プライベート秘密鍵。ファイルの形式はバックエンドに依存する。PEM エンコードされたファイルの拡張子は .pem である。PKCS#12 エンコードされたファイルには、.pfx 拡張子を付ける。ルート・ファイル名は、certs ディレクトリ内の対応する公開鍵ファイルと同じでなければならない。このフォルダは、own フォルダの中にのみ存在する。
crlcertsディレクトリにあるすべてのCA証明書のDERエンコードされたCRLが含まれる。ファイルの拡張子は .crl とする。

最初の接続

初めて接続する場合、クライアントはサーバー証明書を信頼する必要がある。

クライアントは証明書の警告(証明書の詳細)を表示し、証明書を信頼リストに保存できるようにする必要があります。例については、Qt OPC UA Viewer Exampleを参照のこと。

クライアントがサーバ証明書を受け入れたら、再度接続を試みることができる。このとき、サーバはクライアントの証明書を拒否することがあります。これは、一般的なエラー・コードBadSecurityChecksFailed で示されます。サーバーは通常、拒否された証明書を特別なフォルダ(rejected )に保存します。管理者は、これらを信頼リストに移動してクライアントを信頼することができます。これにより、手動でクライアント証明書をサーバー・マシンにコピーする必要がなくなります。

サーバーがクライアントを信頼すると、すぐにセキュリティで接続できるようになります。

© 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.