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!!