如何生成含应用URI的DER格式X509证书实现OPC UA客户端认证?
解决OPC UA客户端SignAndEncrypt连接的证书生成问题
我之前做过OPC UA客户端对接西门子Sofnet服务器的项目,刚好碰到过一模一样的问题——用OpenSSL生成的证书总是缺Subject Alternative Names(SAN)字段里的应用URI,导致服务器拒绝SignAndEncrypt模式的连接。下面给你一步步梳理解决方案,还有一些客户端认证的关键细节。
一、用OpenSSL生成带应用URI的合规证书
核心问题是默认的OpenSSL配置不会自动添加SAN字段,你需要自定义配置文件来强制指定这个字段,尤其是OPC UA要求的应用URI必须放在SAN里(而不是Subject字段)。
1. 编写自定义OpenSSL配置文件
创建一个名为opcua_client.cnf的文件,内容如下(记得替换掉尖括号里的占位符):
[req] default_bits = 2048 prompt = no default_md = sha256 distinguished_name = dn req_extensions = v3_req [dn] C = <YourCountryCode> # 比如CN ST = <YourState> # 比如Beijing L = <YourCity> # 比如Beijing O = <YourOrganization> # 比如YourCompany OU = <YourDepartment> # 比如R&D CN = <YourClientName> # 比如OPCUA_Client_V1 [v3_req] keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alt_names [alt_names] URI.1 = <YourAppURI> # 这里是关键!比如urn:yourcompany:opcua:client:v1 # 如果需要的话,可以添加IP或DNS(可选) # IP.1 = 192.168.1.100 # DNS.1 = client.yourcompany.com
2. 执行OpenSSL命令生成证书
按顺序执行以下命令,生成私钥、CSR、自签名证书,最后转成DER格式:
- 生成2048位RSA私钥:
openssl genrsa -out opcua_client.key 2048 - 生成证书签名请求(CSR):
openssl req -new -key opcua_client.key -out opcua_client.csr -config opcua_client.cnf - 自签名生成X509证书(有效期设为10年,可按需调整):
openssl x509 -req -days 3650 -in opcua_client.csr -signkey opcua_client.key -out opcua_client.crt -extensions v3_req -extfile opcua_client.cnf - 转换成DER格式(服务器要求的格式):
openssl x509 -in opcua_client.crt -outform der -out opcua_client.der
3. 验证证书是否包含应用URI
执行命令查看证书详情,确认SAN字段存在:
openssl x509 -in opcua_client.crt -text -noout
在输出里找X509v3 Subject Alternative Name部分,应该能看到你配置的应用URI,比如:
X509v3 Subject Alternative Name:
URI:urn:yourcompany:opcua:client:v1
二、OPC UA客户端SignAndEncrypt连接的关键思路
证书搞定后,还要注意以下几个细节才能顺利连接:
- 证书信任关系:把你的客户端DER证书导入到西门子Sofnet服务器的信任列表里(通常在Sofnet的配置工具中操作,找到“证书管理”或“信任列表”选项),否则服务器会直接拒绝连接。
- 应用URI严格匹配:客户端代码中设置的
application_uri必须和证书SAN字段里的URI完全一致,大小写、符号都不能错——这是OPC UA认证的核心校验点之一。 - 安全策略匹配:西门子Sofnet常用的安全策略是
Basic256Sha256,客户端必须指定对应的策略,不能用其他不兼容的策略。 - 密钥加载正确:客户端要同时加载DER格式的证书和PEM格式的私钥,确保在SignAndEncrypt模式下能完成签名和加密操作。
简单代码示例(以Python的opcua库为例)
from opcua import Client # 服务器地址 server_url = "opc.tcp://192.168.1.20:4840" client = Client(server_url) # 配置SignAndEncrypt模式、安全策略,加载证书和私钥 client.set_security_string("SignAndEncrypt,Basic256Sha256,opcua_client.der,opcua_client.key") # 必须和证书里的应用URI一致 client.application_uri = "urn:yourcompany:opcua:client:v1" try: client.connect() print("成功连接到Sofnet服务器!") # 这里可以添加读取节点、订阅数据等操作 finally: client.disconnect()
如果连接还是失败,建议查看Sofnet服务器的日志,通常会明确提示是证书验证失败、应用URI不匹配还是安全策略不一致,根据日志调整即可。
内容的提问来源于stack exchange,提问作者Victor Valero Fernandez
相关产品推荐
相关产品推荐

