Home > Software engineering >  "failed to find any PEM data in certificate input" error popup by tls.X509KeyPair
"failed to find any PEM data in certificate input" error popup by tls.X509KeyPair

Time:01-13

I am trying to make are tls cert for HTTPS server by golang x509 package

and i got this error

tls: failed to find any PEM data in certificate input

After some research, I create my Cert like this

func Generatecert()  {
    ca := &x509.Certificate{
        SerialNumber: big.NewInt(2023),
        Subject: pkix.Name{
            Organization:       []string{"Company"},
            OrganizationalUnit: []string{"lol"},
            Country:            []string{"US"},
            Province:           []string{""},
            Locality:           []string{"NY"},
            StreetAddress:      []string{"No street"},
            PostalCode:         []string{"77777"},
        },
        NotBefore:             time.Now(),
        NotAfter:              time.Now().AddDate(10, 0, 0),
        SubjectKeyId:          []byte{1, 2, 3, 4, 5},
        BasicConstraintsValid: true,
        IsCA:                  true,
        ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
        KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
    }

    certpubl, certpriv, err := ed25519.GenerateKey(rand.Reader)
    if err != nil {
        log.Println("key generate failed", err)
        return
    }

    certCert, err := x509.CreateCertificate(rand.Reader, ca, ca, certpubl, certpriv)
    if err != nil {
        log.Println("create cert failed", err)
        return
    }

    out := &bytes.Buffer{}

    //Encoding cert
    certtestpem := &pem.Block{Type: "CERTIFICATE", Bytes: certCert}
    pem.Encode(out, certtestpem)
    publicCert := out.Bytes()
    certDERBlock, publicCert := pem.Decode(publicCert)

    //Check Decoded cert
    print(certDERBlock.Type, "\n")
    if publicCert != nil {
        print("publicCert nil\n")
    }

    //Encoding Private Key
    out.Reset()
    privatepem, _ := x509.MarshalPKCS8PrivateKey(certpriv)
    pem.Encode(out, &pem.Block{Type: "PRIVATE KEY", Bytes: privatepem})
    privitKey := out.Bytes()

    //check KeyPair
    _, err = tls.X509KeyPair(publicCert, privitKey)
    if err != nil {
        print(err.Error())
    }
}

it show the error like under

CERTIFICATE

publicCert nil

tls: failed to find any PEM data in certificate input

I try Decode after pem.EncodeToMemory

the pem.Type are correct, but variable "publicCert" is nil, And I try add are \n begin of the cert, it did nothing, but the cert itself is not nil, Can Somebody Help me with this

What sould I do to make a working Tls???

CodePudding user response:

after some debug, it seem like the pem.Encode function not working for me,

so i change it to pem.EncodeToMemory and it working thank you for the help.

CodePudding user response:

There are several problems in this code

publicCert := out.Bytes()

Checking the content of publicCert at this stage shows the expect value. But the following statement will simply overwrite publicCert:

certDERBlock, publicCert := pem.Decode(publicCert)

This can be seen by checking publicCert after this statement. As documented publicCert will now show the data after the actual certificate.

It should be instead

certDERBlock, _ := pem.Decode(publicCert)

Checking the content of publicCert after this corrected statement shows the expected value again.

out.Reset()
privatepem, _ := x509.MarshalPKCS8PrivateKey(certpriv)
pem.Encode(out, &pem.Block{Type: "PRIVATE KEY", Bytes: privatepem})
privitKey := out.Bytes()

This will get the expected value into privitKey. But, it will change publicCert since it is just a slice of out and out has been changed the the operations. Thus out will now contain at the beginning the privitKey and no longer the start of the certificate - and this is reflected in the value of publicCert.

See also the documentation for bytes.Buffer.Bytes

The slice is valid for use only until the next buffer modification (that is, only until the next call to a method like Read, Write, Reset, or Truncate)

So instead of just resetting the existing buffer

out.Reset()

it would be better to create a new buffer for privitKey and keep the existing one for publicCert

out = &bytes.Buffer{}
  • Related