跳到主要内容

证书生成与配置

前置阅读

1. 生成客户端 PFX

用 CertificateManager (推荐)

CertificateManager.GenerateSelfSigned(
outPath: @"C:\certs\client.pfx",
password: "123456",
commonName: "MyClient",
applicationUri: "urn:my-company:my-client",
organization: "My Company",
country: "CN",
validDays: 365,
keySize: 2048);

会生成同名 .der 公钥文件 (client.der), 用于导入服务端 trusted/.

用 OpenSSL (替代)

openssl req -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes \
-subj "/CN=MyClient/O=Darra/C=CN" \
-addext "subjectAltName=URI:urn:my-company:my-client"

openssl pkcs12 -export -out client.pfx -inkey key.pem -in cert.pem -password pass:123456

2. 服务端导入信任

把客户端公钥 (.der.pem) 拷贝到服务端的"受信任客户端证书"目录:

Server路径
Darra SimulatorServer<simulator>/pki/trusted/certs/
open62541 example<server>/pki/trusted/certs/
UaExpert设置 → Certificates → Trust

3. 客户端构造时传 PFX

using var ua = new DarraOpcUa(
endpointUrl: "opc.tcp://server:4840",
securityMode: MessageSecurityMode.SignAndEncrypt,
clientCertPath: @"C:\certs\client.pfx",
clientKeyPath: "123456", // PFX 密码
serverCertPath: null); // null = TOFU (Trust On First Use)
ua.Connect();

4. 服务端证书 TOFU

第一次连接时, 客户端会信任服务端证书并保存指纹. 之后每次连接校验指纹一致, 不一致 (中间人) 拒绝.

如果不想 TOFU, 显式传服务端证书 DER 路径:

serverCertPath: @"C:\certs\server.der"

故障排查

StatusCode原因解决
BadCertificateUntrusted服务端没信任客户端把 client.der 拷到服务端 trusted/certs/
BadCertificateInvalid证书过期 / 未生效重新生成
BadCertificateUriInvalid证书 SAN.URI 与 ApplicationUri 不匹配重新生成时确保 applicationUri 一致
BadCertificateHostNameInvalid证书 SAN.DNS 与连接的 host 不匹配生成时加 subjectAltName=DNS:server.example.com
BadSecurityChecksFailed通用安全校验失败看服务端日志查具体原因
BadSecurityModeRejected服务端不支持该 SecurityModeGetEndpoints 看服务端实际支持哪些
BadSecurityPolicyRejected服务端不支持 Basic256Sha256服务端配置开启该 Policy

SAN URI 重要性

OPC UA 校验客户端证书 SAN 中必须有 URI: 字段, 且与 ApplicationUri 一致. 这是防伪造的关键, 必须正确设置. 用 CertificateManager.Inspect(...) 验证:

var info = CertificateManager.Inspect(@"C:\certs\client.pfx", "123456");
if (string.IsNullOrEmpty(info.SubjectAltNameUri))
Console.WriteLine("ERROR: Certificate missing SAN URI - regenerate!");

时间同步 (NTP)

加密模式下双方校验时间戳, 偏差超过 ~10 分钟会被拒绝. 生产环境必须配 NTP, 时间偏差控制在秒级.

# Windows
w32tm /resync

# Linux
sudo timedatectl set-ntp true

下一步