package main // ver. 1.3a // coded by Kenar import ( . "fmt" "os" "encoding/pem" "crypto/x509" "crypto/rsa" "crypto/ecdsa" "strconv" ) var usage = `usage: pemdump cert.pem [n] n is 1,2,... n: certificate number in cert.pem to be dumped if n is not given, all certificates will be dumped` func Error(s interface{}){ Fprintln(os.Stderr,s) os.Exit(1) } func check(err error) { if err != nil { Error(err) } } // maybe nice. https://oidref.com var oidmap = map[string]string{ "2.5.4.3": "Common Name", "2.5.4.5": "Serial Number", "2.5.4.6": "Country Name", "2.5.4.7": "Locality Name", "2.5.4.8": "State or Province name", "2.5.4.9": "Street Address", "2.5.4.10": "Organization Name", "2.5.4.11": "Organization Unit Name", "2.5.4.17": "Postal Code", "2.5.29.14": "Subject Key Id", "2.5.29.15": "Key Usage", "2.5.29.16": "Private Key Usage Period", "2.5.29.37": "Extended Key Usage", "2.5.29.35": "Authority Key Id", "2.5.29.19": "Basic Constraints", "2.5.29.17": "Subject Alt Name", "2.5.29.32": "Certificate Policies", "2.5.29.31": "CRL Distribution Points", "2.5.29.20": "CRL Number", "1.3.6.1.5.5.7.1.1": "Authority Info Access", "1.3.6.1.5.5.7.48.1": "Authority Info Access Ocsp", "1.3.6.1.5.5.7.48.2": "Authority Info Access Issuers", "1.2.840.113549.1.1.1": "RSA Encryption", "1.2.840.113549.1.1.5": "Sha1 With Rsa Encryption", "1.2.840.113549.1.1.11": "Sha256 With Rsa Encryption", "1.2.840.113549.1.9.1": "Email Address", "1.3.6.1.4.1.11129.2.4.2": "Signed Certificate Timestamp", } func dotOid(input []int) (out string) { out += Sprintf("%d",input[0]) for k:=1; k < len(input); k++ { out += Sprintf(".%d",input[k]) } return } // look src/crypto/x509/x509.go for Certificate func dump(certp *x509.Certificate){ cert := *certp Printf("Raw %x\n",string(cert.Raw)) Printf("RawTBSCertificate %x\n",string(cert.RawTBSCertificate)) Printf("RawSubjectPublicKeyInfo %x\n",string(cert.RawSubjectPublicKeyInfo)) Printf("RawSubject %x\n",string(cert.RawSubject)) Printf("RawIssuer %x\n",string(cert.RawIssuer)) Printf("Signature %x\n",string(cert.Signature)) Println("SignatureAlgorithm",cert.SignatureAlgorithm) Println("PublicKeyAlgorithm",cert.PublicKeyAlgorithm) alg := Sprintf("%v", cert.PublicKeyAlgorithm) switch(alg){ case "RSA": t := cert.PublicKey.(*rsa.PublicKey) Printf("PublicKey N=%x\n", t.N) Printf("PublicKey E=%x\n", t.E) case "ECDSA": t := cert.PublicKey.(*ecdsa.PublicKey) Printf("CurveParams %v\n", t.Curve) Printf("PublicKey X=%x\n", t.X) Printf("PublicKey Y=%x\n", t.Y) default: Error("unsupported PublicKeyAlgorithm") } // next 3 lines was very difficult to find out. look the ref[2] Println("Version",cert.Version) s := cert.SerialNumber Printf("SerialNumber %v (%x)\n",s,s) Println("Issuer",cert.Issuer) Println("Subject",cert.Subject) Println("NotBefore",cert.NotBefore) Println("NotAfter",cert.NotAfter) Println("KeyUsage",cert.KeyUsage) Println("IsCA",cert.IsCA) Printf("SubjectKeyId %x\n",cert.SubjectKeyId) Printf("AuthorityKeyId %x\n",cert.AuthorityKeyId) Printf("DNSNames %s\n",cert.DNSNames) Printf("EmailAddresses %s\n",cert.EmailAddresses) Printf("IPAddresses %s\n",cert.IPAddresses) Printf("URIs %s\n",cert.URIs) // Extensions are version 3 only for k:=0; k < len(cert.Extensions); k++ { t := cert.Extensions[k] // Printf("%T\n",t) // pkix.Extension // pkix.Extension has only three elements. look Note1 Printf("Extensions %d Id=%v (%s) Critical=%v Value=%x\n",k, t.Id, oidmap[dotOid(t.Id)], t.Critical, t.Value) } for k:=0; k < len(cert.ExtraExtensions); k++ { t := cert.ExtraExtensions[k] Printf("ExtraExtensions %d Id=%v (%s) Critical=%v Value=%x\n",k, t.Id, oidmap[dotOid(t.Id)], t.Critical, t.Value) } } func main() { var pb = make([]*pem.Block,0) var pb1 *pem.Block var n int var err error var bs []byte args := os.Args[1:] if len(args) != 1 && len(args) != 2{ Error(usage) } bs,err = os.ReadFile(args[0]) check(err) pb1,bs = pem.Decode(bs) for k:=0; pb1 != nil ; k++ { pb = append(pb[:], pb1) pb1,bs = pem.Decode(bs) } max := len(pb) if len(args) == 2 { n,err = strconv.Atoi(args[1]) check(err) if n < 1 || n >= max { Error(usage) } cert,err := x509.ParseCertificate(pb[n-1].Bytes) check(err) dump(cert) return } for k:=0; k < max; k++ { if k != 0 { Println() } cert,err := x509.ParseCertificate(pb[k].Bytes) check(err) dump(cert) } }