Generate private keys and x509 certificates using the Golang crypto package's code,unable to connect to my mqtts server normally

I need to generate a private key and certificate to connect to my mqtts server.

I generated a private key and a certificate using Golang’s crypto package, but I am unable to connect to my mqtts server properly. But the certificate I created through OpenSSL based on the private key I generated using Golang code can connect to my mqtts server normally.

go version:
go version go1.20.1 darwin/arm64

I haven’t tried the latest version of Golang yet

I used this code to create a private key and certificate:

func GenerateCertificate(certificatePath string, keyPath string) error {
    key, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)

    serialNumber, err := rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
    if err != nil {
        return err
    }
    now := time.Now()
    template := x509.Certificate{
        SerialNumber: serialNumber,
        Subject: pkix.Name{
            CommonName:   "localhost",
            Country:      []string{"AU"},
            Organization: []string{"Internet Widgits Pty Ltd"},
            Province:     []string{"Some-State"},
        },
        Issuer: pkix.Name{
            CommonName:   "localhost",
            Country:      []string{"AU"},
            Organization: []string{"Internet Widgits Pty Ltd"},
            Province:     []string{"Some-State"},
        },
        NotBefore:          now,
        NotAfter:           now.AddDate(10, 0, 0),
        PublicKeyAlgorithm: x509.ECDSA,
        SignatureAlgorithm: x509.ECDSAWithSHA256,
    }

    derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
    var certificateOut, keyOut io.Writer

    if _, e := os.Stat(keyPath); os.IsNotExist(e) {
        if _, err = os.Create(keyPath); err != nil {
            return err
        }
    }
    keyOut, err = os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
        return err
    }
    if _, e := os.Stat(certificatePath); os.IsNotExist(e) {
        if _, err = os.Create(certificatePath); err != nil {
            return err
        }
    }
    certificateOut, err = os.OpenFile(certificatePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
        return err
    }

    secp256r1, err := asn1.Marshal(asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7})
    if err != nil {
        return err
    }
    paramBlock := pem.EncodeToMemory(&pem.Block{Type: "EC PARAMETERS", Bytes: secp256r1})
    if _, err := keyOut.Write(paramBlock); err != nil {
        return err
    }
    b, err := x509.MarshalECPrivateKey(key)
    privBlock := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
    
    if _, err := keyOut.Write(privBlock);err != nil {
        return err
    }

    certBlock := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})

    certificateOut.Write(certBlock)
    return nil
}

Next, I will use the created private key and certificate to connect to my mqtts server:

func NewTLSConfig(certFile string, privateKey string) (*tls.Config, error) {

    cert, err := tls.LoadX509KeyPair(certFile, privateKey)
    if err != nil {
        return nil, err
    }

    return &tls.Config{
        ClientAuth:         tls.NoClientCert,
        ClientCAs:          nil,
        InsecureSkipVerify: true,
        MinVersion:         tls.VersionTLS12,
        MaxVersion:         tls.VersionTLS12,
        Certificates:       []tls.Certificate{cert},
    }, nil
}

if tlsConfig, err := util.NewTLSConfig("./config/certs/cert.pem", "./config/certs/key.pem"); err == nil {
    opts.SetTLSConfig(tlsConfig)
} else {
    return err
}

t.Client = mqtt.NewClient(opts)
if token := t.Client.Connect(); token.Wait() && token.Error() != nil {
    logrus.Error("Connect to Thingsboard failed:", token.Error())
    return token.Error()
}

And then my mqtts server couldn’t receive any certificates
Screenshot of mqtts server debugging

But I used the openssl command to create a certificate based on the private key I created using Golang code, and then connected to my mqtts server in the same way, which is normal. The command is as follows:

openssl req -new -key key.pem -x509 -nodes -days 365 -out cert.pem

Screenshot of openssl command
Screenshot of mqtts server debugging

May I ask what I should do to ensure that the cert.pem created by my code can be used properly and connected to my mqtts? Thank you very much!!

I cannot help you much in regards with mttq and how it accepts any given certificate.

I’ve almost completed my own tool that manages my own Private Key Infrastructure, from the custom Certificate Authority, to the “standard” SSL certs. For those certs, it creates the CSR (Certificate Signing Request), signs the certificate, and stores it on-disk, PEM-encoded.

The code is working, my LAN already works with it. You might wish to have a look at GitHub - jeanfrancoisgratton/certificateManager: Go tool to manage server certificates and custom root CA certs , specifically under src/cert/, and of course, the README.md.

This might help you, especially as you could get rid of running an external tool (openssl) to generate keys, etc.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.