Bhaskar
Bhaskar

Reputation: 10681

How to parse collection of PEM certs

I have a collection of pem certs in a string, that I want to bind to a TLS endpoint, how can I effectively convert them to CRT files (i.e.public.crt) and key file (i.e. private.key), for binding it to the endpoint:

Input string:

-----BEGIN PRIVATE KEY-----
MIIE3oydueOANJHhvL3yvJdTphoev5GO7go+ByYOO/l54u5O2PxMeX+AjAb6Axmq
livIuhw=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIE3oydueOANJHhvL3yvJdTphoev5GO7go+ByYOO/l54u5O2PxMeX+AjAb6Axmq
livIuhw=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE3oydueOANJHhvL3yvJdTphoev5GO7go+ByYOO/l54u5O2PxMeX+AjAb6Axmq
asdsa312asdsadasdsad=
-----END CERTIFICATE-----

My code to bind would be:

https_r := mux.NewRouter()
err_https := http.ListenAndServeTLS(serviceEndpoint, "/etc/pki/tls/certs/public.crt", "/etc/pki/tls/certs/private.key", https_r)
    if err_https != nil {
        log.Fatal("Web server (HTTPS): ", err_https)
    }

I have tried two approaches:

  1. I tried to decode it to a PEM block, but it only reads one of the certs and drops the rest.
  2. I tried to create a CertPool out of the string, but it also loads one of the cert.

Ideally, I would not like to perform a bunch of string parsing, which would be prone to break.

Any other way would highly be appreciated.

Upvotes: 6

Views: 6605

Answers (1)

Alexander Dzyoba
Alexander Dzyoba

Reputation: 4189

I tried to decode it to a PEM block, but it only reads one of the certs and drops the rest.

The trick is to handle the rest of the PEM blocks. It is returned in pem.Decode seconds result. Here is how it can be done:

    for block, rest := pem.Decode(data); block != nil; block, rest = pem.Decode(rest) {
        switch block.Type {
        case "CERTIFICATE":
            cert, err := x509.ParseCertificate(block.Bytes)
            if err != nil {
                panic(err)
            }

            // Handle certificate
            fmt.Printf("%T %#v\n", cert, cert)

        case "PRIVATE KEY":
            key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
            if err != nil {
                panic(err)
            }

            // Handle private key
            fmt.Printf("%T %#v\n", key, key)

        default:
            panic("unknown block type")
        }
    }

Upvotes: 8

Related Questions