首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带证书的Golang Opc UA客户端实现

带证书的Golang Opc UA客户端实现
EN

Stack Overflow用户
提问于 2022-01-04 14:26:19
回答 1查看 705关注 0票数 1

我正在尝试用证书连接本地Kepware OPC UA服务器。OPC UA服务器安全信息:

在golang应用程序中,我使用"github.com/gopcua/opcua/ua“opc客户端包。我创建密钥对,并给它们提供变量的路径,并在配置中使用它们:

代码语言:javascript
运行
复制
    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密钥对来连接服务器。

EN

回答 1

Stack Overflow用户

发布于 2022-01-04 15:21:40

为了使用任何以上的安全策略,或者使用用户名/密码登录,您需要有一个现有的X.509证书,或者自己生成一个证书。

注意,证书分为两个部分,一个是公共证书,另一个是私钥。你两者都需要。公共证书将被发送到Kepware服务器,而私钥将留在客户端并用于加密和解密。

代码语言:javascript
运行
复制
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证书。

代码语言:javascript
运行
复制
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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70580290

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档