// Show Certificate information // SPDX-License-Identifier: MPL-2.0 // Copyright © 2025 Balakrishnan Balasubramanian package main import ( "crypto/x509" "encoding/json" "encoding/pem" "flag" "fmt" "io/ioutil" "os" ) func main() { jsonOut := flag.Bool("json", false, "output JSON with all certs/fields") flag.Parse() if flag.NArg() < 1 { fmt.Println("usage: certinfo [--json] ") os.Exit(2) } path := flag.Arg(0) certs, err := parseCertinfo(path) if err != nil { fmt.Println("parse error:", err) os.Exit(1) } if *jsonOut { jsonBytes, err := json.Marshal(certs) if err != nil { fmt.Println("marshal error:", err) os.Exit(1) } fmt.Println(string(jsonBytes)) return } // Usually just the first one is interesting cert := certs[0] fmt.Println("Subject :", cert.Subject.String()) fmt.Println("Issuer :", cert.Issuer.String()) fmt.Println("Serial :", cert.SerialNumber.String()) fmt.Println("NotBefore :", cert.NotBefore) fmt.Println("NotAfter :", cert.NotAfter) fmt.Println("DNSNames :", cert.DNSNames) fmt.Println("SignatureAlgo :", cert.SignatureAlgorithm) fmt.Println("PublicKeyAlgo :", cert.PublicKeyAlgorithm) } func parseCertinfo(filename string) ([]*x509.Certificate, error) { data, err := ioutil.ReadFile(filename) if err != nil { return nil, err } var certs []*x509.Certificate for { var block *pem.Block block, data = pem.Decode(data) if block == nil { break } if block.Type != "CERTIFICATE" { fmt.Fprintf(os.Stderr, "warning: Ignoring block type: %s\n", block.Type) continue } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, err } certs = append(certs, cert) } return certs, nil }