ecdsa.com

Decode a certificate · Go

How to decode an X.509 certificate in Go

Go parses X.509 certificates with crypto/x509 from the standard library — the same code path the TLS stack uses. One pem.Decode plus one ParseCertificate call yields a struct with subject, validity, signature algorithm and the typed public key.

Tested with Go 1.26 (standard library only).

Same recipe in:Node.jsPythonGoOpenSSL
decode_cert.go — parse and print the core fields
package main
 
import (
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
"time"
)
 
func main() {
pemBytes, _ := os.ReadFile("cert.pem")
block, _ := pem.Decode(pemBytes) // type "CERTIFICATE"
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
panic(err)
}
 
fmt.Println("subject:", cert.Subject)
fmt.Println("issuer:", cert.Issuer)
fmt.Println("valid:", cert.NotBefore, "->", cert.NotAfter)
fmt.Println("serial:", cert.SerialNumber)
fmt.Println("sig alg:", cert.SignatureAlgorithm) // ECDSA-SHA256
 
if pub, ok := cert.PublicKey.(*ecdsa.PublicKey); ok {
fmt.Println("EC key on", pub.Curve.Params().Name) // P-256
}
 
fmt.Println("days until expiry:",
int(time.Until(cert.NotAfter).Hours()/24))
}

How it works

  1. pem.Decode returns the first block and the rest of the input — loop on the rest to handle bundle files with a whole chain.
  2. cert.PublicKey is typed any; a type switch over *ecdsa.PublicKey, *rsa.PublicKey and ed25519.PublicKey covers real-world certs.
  3. NotBefore/NotAfter are time.Time — expiry math is ordinary time arithmetic, no string parsing.
  4. Subject alternative names are pre-parsed: cert.DNSNames, cert.IPAddresses and cert.EmailAddresses — no need to dig through cert.Extensions for the common cases.

Gotchas

  • pem.Decode returns nil (not an error) when the input has no PEM block — a DER file, a typo'd path. Check block != nil before touching block.Bytes or you trade a clear message for a nil-pointer panic.
  • cert.SignatureAlgorithm describes how the CA signed this certificate; the certificate's own key type lives in cert.PublicKeyAlgorithm and cert.PublicKey. ECDSA leaf, RSA chain is common.
  • For trust decisions use cert.Verify(x509.VerifyOptions{...}) with a root pool — ParseCertificate accepts expired and self-signed certificates by design.

Related recipes