我正在尝试用证书连接本地Kepware OPC UA服务器。OPC UA服务器安全信息:
在golang应用程序中,我使用"github.com/gopcua/opcua/ua“opc客户端包。我创建密钥对,并给它们提供变量的路径,并在配置中使用它们:
opts := []opcua.Option{
opcua.SecurityPolicy(relatedConnection.SecurityPolicy),
opcua.SecurityModeString(relatedConnection.SecurityMode),
opcua.CertificateFile(certFile),
opcua.PrivateKeyFile(keyFile),
opcua.AutoReconnect(true),
opcua.ReconnectInterval(time.Second * 5),
opcua.RequestTimeout(time.Second * 3),
}
当安全策略和模式为空时,我可以毫无问题地连接到服务器。当我选择这些安全策略时,我不知道如何实现代码或ssl密钥对来连接服务器。
发布于 2022-01-04 15:21:40
为了使用任何以上的安全策略,或者使用用户名/密码登录,您需要有一个现有的X.509证书,或者自己生成一个证书。
注意,证书分为两个部分,一个是公共证书,另一个是私钥。你两者都需要。公共证书将被发送到Kepware服务器,而私钥将留在客户端并用于加密和解密。
endpoints, err := opcua.GetEndpoints(context.Background(), cfg.Endpoint)
if err != nil {
return nil, fmt.Errorf("OPC GetEndpoints: %w", err)
}
policy := ua.SecurityPolicyURINone // Replace this with a constant of your security policy
mode := ua.MessageSecurityModeNone // Replace this with a constant of your security mode
ep := opcua.SelectEndpoint(endpoints, policy, mode)
c, err := generateCert() // This is where you generate the certificate
if err != nil {
return nil, fmt.Errorf("generateCert: %w", err)
}
pk, ok := c.PrivateKey.(*rsa.PrivateKey) // This is where you set the private key
if !ok {
return nil, fmt.Errorf("invalid private key")
}
cert := c.Certificate[0]
opts := []opcua.Option{
opcua.SecurityPolicy(policy),
opcua.SecurityMode(mode),
opcua.PrivateKey(pk),
opcua.Certificate(cert), // Set the certificate for the OPC UA Client
opcua.AuthUsername(cfg.Username, cfg.Password), // Use this if you are using username and password
opcua.SecurityFromEndpoint(ep, ua.UserTokenTypeUserName),
opcua.SessionTimeout(30 * time.Minute),
opcua.AutoReconnect(true),
opcua.ReconnectInterval(time.Second * 10),
opcua.Lifetime(30 * time.Minute),
opcua.RequestTimeout(3 * time.Second),
}
使用以下方法生成X.509证书。
func generateCert() (*tls.Certificate, error) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, fmt.Errorf("failed to generate private key: %s", err)
}
notBefore := time.Now()
notAfter := notBefore.Add(365 * 24 * time.Hour) // 1 year
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, fmt.Errorf("failed to generate serial number: %s", err)
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Test Client"},
},
NotBefore: notBefore,
NotAfter: notAfter,
KeyUsage: x509.KeyUsageContentCommitment | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
host := "urn:testing:client"
if ip := net.ParseIP(host); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, host)
}
if uri, err := url.Parse(host); err == nil {
template.URIs = append(template.URIs, uri)
}
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
if err != nil {
return nil, fmt.Errorf("failed to create certificate: %s", err)
}
certBuf := bytes.NewBuffer(nil)
if err := pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
return nil, fmt.Errorf("failed to encode certificate: %s", err)
}
keyBuf := bytes.NewBuffer(nil)
if err := pem.Encode(keyBuf, pemBlockForKey(priv)); err != nil {
return nil, fmt.Errorf("failed to encode key: %s", err)
}
cert, err := tls.X509KeyPair(certBuf.Bytes(), keyBuf.Bytes())
return &cert, err
}
下面是一个直接来自gopcua项目的示例:https://github.com/gopcua/opcua/blob/main/examples/crypto/generate_cert.go
https://stackoverflow.com/questions/70580290
复制相似问题