Make text certs shorter, existing text output now has a --verbose flag

This commit is contained in:
Matthew McPherrin
2017-02-25 16:33:09 -08:00
parent fca450a6f0
commit f5f617c58f
9 changed files with 118 additions and 35 deletions
+46 -13
View File
@@ -26,15 +26,13 @@ import (
"text/template"
"time"
"encoding/asn1"
"github.com/fatih/color"
)
var layout = `
var verboseLayout = `
{{- define "PkixName" -}}
{{- range .Names}}
{{ .Type | oidify }}: {{ .Value }}
{{ .Type | oidName }}: {{ .Value }}
{{- end -}}
{{end -}}
@@ -66,6 +64,39 @@ Email Addresses:{{range .EmailAddresses}}
Warnings:{{range .Warnings}}
{{. | redify}}{{end}}{{end}}`
var layout = `
{{- define "PkixName" -}}
{{- range $index, $element := .Names}}
{{- if $index}}, {{end}}
{{- $short := $element.Type | oidShort }}
{{- if $short -}}
{{ $short }}={{ .Value }}
{{- end}}
{{- end -}}
{{end -}}
{{- if .Alias}}{{.Alias}}
{{end -}}
Not Before: {{.NotBefore | certStart}}
Not After : {{.NotAfter | certEnd}}
Subject: {{template "PkixName" .Subject.Name}}
Issuer: {{template "PkixName" .Issuer.Name}}
{{- if .NameConstraints}}
Name Constraints {{if .PermittedDNSDomains.Critical}}(critical){{end}}: {{range .NameConstraints.PermittedDNSDomains}}
{{.}}{{end}}{{end}}
{{- if .AltDNSNames}}
Alternate DNS Names:{{range .AltDNSNames}}
{{.}}{{end}}{{end}}
{{- if .AltIPAddresses}}
Alternate IP Addresses:{{range .AltIPAddresses}}
{{.}}{{end}}{{end}}
{{- if .EmailAddresses}}
Email Addresses:{{range .EmailAddresses}}
{{.}}{{end}}{{end}}
{{- if .Warnings}}
Warnings:{{range .Warnings}}
{{. | redify}}{{end}}{{end}}`
type certWithName struct {
name string
file string
@@ -110,15 +141,15 @@ func EncodeX509ToObject(cert *x509.Certificate) interface{} {
}
// EncodeX509ToText encodes an X.509 certificate into human-readable text.
func EncodeX509ToText(cert *x509.Certificate) []byte {
return displayCert(createSimpleCertificate("", cert))
func EncodeX509ToText(cert *x509.Certificate, verbose bool) []byte {
return displayCert(createSimpleCertificate("", cert), verbose)
}
// displayCert takes in a parsed certificate object
// (for jceks certs, blank otherwise), and prints out relevant
// information. Start and end dates are colored based on whether or not
// the certificate is expired, not expired, or close to expiring.
func displayCert(cert simpleCertificate) []byte {
func displayCert(cert simpleCertificate, verbose bool) []byte {
funcMap := template.FuncMap{
"certStart": certStart,
"certEnd": certEnd,
@@ -127,10 +158,16 @@ func displayCert(cert simpleCertificate) []byte {
"hexify": hexify,
"keyUsage": keyUsage,
"extKeyUsage": extKeyUsage,
"oidify": oidify,
"oidName": oidName,
"oidShort": oidShort,
}
t := template.New("Cert template").Funcs(funcMap)
t, err := t.Parse(layout)
var err error
if verbose {
t, err = t.Parse(verboseLayout)
} else {
t, err = t.Parse(layout)
}
if err != nil {
// Should never happen
panic(err)
@@ -221,7 +258,3 @@ func certEnd(end time.Time) string {
func redify(text string) string {
return red.SprintfFunc()("%s", text)
}
func oidify(oid asn1.ObjectIdentifier) string {
return describeOid(oid).Name
}
+23 -14
View File
@@ -2,10 +2,11 @@ package lib
import "encoding/asn1"
// OidDescription returns a human-readable name, a snake_case slug suitable as a json key,
// OidDescription returns a human-readable name, a short acronym from RFC1485, a snake_case slug suitable as a json key,
// and a boolean describing whether multiple copies can appear on an X509 cert.
type OidDescription struct {
Name string
Short string
Slug string
Multiple bool
}
@@ -14,21 +15,29 @@ func describeOid(oid asn1.ObjectIdentifier) OidDescription {
raw := oid.String()
// Multiple should be true for any types that are []string in x509.pkix.Name. When in doubt, set it to true.
names := map[string]OidDescription{
"2.5.4.3": {"CommonName", "common_name", false},
"2.5.4.5": {"EV Incorporation Registration Number", "ev_registration_number", false},
"2.5.4.6": {"Country", "country", true},
"2.5.4.7": {"Locality", "locality", true},
"2.5.4.8": {"Province", "province", true},
"2.5.4.10": {"Organization", "organization", true},
"2.5.4.11": {"Organizational Unit", "organizational_unit", true},
"2.5.4.15": {"Business Category", "business_category", true},
"1.2.840.113549.1.9.1": {"Email Address", "email_address", true},
"1.3.6.1.4.1.311.60.2.1.1": {"EV Incorporation Locality", "ev_locality", true},
"1.3.6.1.4.1.311.60.2.1.2": {"EV Incorporation Province", "ev_province", true},
"1.3.6.1.4.1.311.60.2.1.3": {"EV Incorporation Country", "ev_country", true},
"2.5.4.3": {"CommonName", "CN", "common_name", false},
"2.5.4.5": {"EV Incorporation Registration Number", "", "ev_registration_number", false},
"2.5.4.6": {"Country", "C", "country", true},
"2.5.4.7": {"Locality", "L", "locality", true},
"2.5.4.8": {"Province", "ST", "province", true},
"2.5.4.10": {"Organization", "O", "organization", true},
"2.5.4.11": {"Organizational Unit", "OU", "organizational_unit", true},
"2.5.4.15": {"Business Category", "", "business_category", true},
"1.2.840.113549.1.9.1": {"Email Address", "", "email_address", true},
"1.3.6.1.4.1.311.60.2.1.1": {"EV Incorporation Locality", "", "ev_locality", true},
"1.3.6.1.4.1.311.60.2.1.2": {"EV Incorporation Province", "", "ev_province", true},
"1.3.6.1.4.1.311.60.2.1.3": {"EV Incorporation Country", "", "ev_country", true},
}
if description, ok := names[raw]; ok {
return description
}
return OidDescription{raw, raw, true}
return OidDescription{raw, "", raw, true}
}
func oidShort(oid asn1.ObjectIdentifier) string {
return describeOid(oid).Short
}
func oidName(oid asn1.ObjectIdentifier) string {
return describeOid(oid).Name
}
+4 -3
View File
@@ -33,7 +33,8 @@ import (
)
var (
app = kingpin.New("certigo", "A command line certificate examination utility.")
app = kingpin.New("certigo", "A command line certificate examination utility.")
verbose = app.Flag("verbose", "Print verbose").Short('v').Bool()
dump = app.Command("dump", "Display information about a certificate from a file/stdin.")
dumpFiles = dump.Arg("file", "Certificate file to dump (or stdin if not specified).").ExistingFiles()
@@ -91,7 +92,7 @@ func main() {
} else {
for i, cert := range result.Certificates {
fmt.Fprintf(stdout, "** CERTIFICATE %d **\n", i+1)
fmt.Fprintf(stdout, "%s\n\n", lib.EncodeX509ToText(cert))
fmt.Fprintf(stdout, "%s\n\n", lib.EncodeX509ToText(cert, *verbose))
}
}
}
@@ -129,7 +130,7 @@ func main() {
fmt.Fprintf(stdout, "%s\n\n", lib.EncodeTLSToText(result.TLSConnectionState))
for i, cert := range result.Certificates {
fmt.Fprintf(stdout, "** CERTIFICATE %d **\n", i+1)
fmt.Fprintf(stdout, "%s\n\n", lib.EncodeX509ToText(cert))
fmt.Fprintf(stdout, "%s\n\n", lib.EncodeX509ToText(cert, *verbose))
}
printVerifyResult(stdout, *result.VerifyResult)
}
+1 -1
View File
@@ -107,7 +107,7 @@ Set up test data.
Dump a live cert chain (squareup-chain.crt)
$ certigo dump squareup-chain.crt
$ certigo --verbose dump squareup-chain.crt
** CERTIFICATE 1 **
Serial: 260680855742043049380997676879525498489
Not Before: 2016-07-15 20:15:52 +0000 UTC
+1 -1
View File
@@ -51,7 +51,7 @@ Set up test data.
Dump PEM blocks from a JCEKS keystore.
$ certigo dump --pem --password password example.jceks
$ certigo --verbose dump --pem --password password example.jceks
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAyjhKEojYzEPP81BXEFvPS1sPlHk1yhsDQ0qRo8ovIwSmdZVj
25zJq4yOg2fUXnrxx86gXSmbfvTRTxRM+3YwzEQciLiYUb84XxQX5WiHUnjZNvja
+40
View File
@@ -0,0 +1,40 @@
Set up test data.
$ cat > example-leaf.crt <<EOF
> -----BEGIN CERTIFICATE-----
> MIIDfDCCAmSgAwIBAgIJANWAkzF7PA8/MA0GCSqGSIb3DQEBCwUAMFUxCzAJBgNV
> BAYTAlVTMQswCQYDVQQIEwJDQTEQMA4GA1UEChMHY2VydGlnbzEQMA4GA1UECxMH
> ZXhhbXBsZTEVMBMGA1UEAxMMZXhhbXBsZS1sZWFmMB4XDTE2MDYxMDIyMTQxMVoX
> DTIzMDQxNTIyMTQxMVowVTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRAwDgYD
> VQQKEwdjZXJ0aWdvMRAwDgYDVQQLEwdleGFtcGxlMRUwEwYDVQQDEwxleGFtcGxl
> LWxlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7stSvfQyGuHw3
> v34fisqIdDXberrFoFk9ht/WdXgYzX2uLNKdsR/J5sbWSl8K/5djpzj31eIzqU69
> w8v7SChM5x9bouDsABHz3kZucx5cSafEgJojysBkcrq3VY+aJanzbL+qErYX+lhR
> pPcZK6JMWIwar8Y3B2la4yWwieecw2/WfEVvG0M/DOYKnR8QHFsfl3US1dnBM84c
> zKPyt9r40gDk2XiH/lGts5a94rAGvbr8IMCtq0mA5aH3Fx3mDSi3+4MZwygCAHrF
> 5O5iSV9rEI+m2+7j2S+jHDUnvV+nqcpb9m6ENECnYX8FD2KcqlOjTmw8smDy09N2
> Np6i464lAgMBAAGjTzBNMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAs
> BgNVHREEJTAjhwR/AAABhxAAAAAAAAAAAAAAAAAAAAABgglsb2NhbGhvc3QwDQYJ
> KoZIhvcNAQELBQADggEBAGM4aa/qrURUweZBIwZYv8O9b2+r4l0HjGAh982/B9sM
> lM05kojyDCUGvj86z18Lm8mKr4/y+i0nJ+vDIksEvfDuzw5ALAXGcBzPJKtICUf7
> LstA/n9NNpshWz0kld9ylnB5mbUzSFDncVyeXkEf5sGQXdIIZT9ChRBoiloSaa7d
> vBVCcsX1LGP2LWqKtD+7nUnw5qCwtyAVT8pthEUxFTpywoiJS5ZdzeEx8MNGvUeL
> Fj2kleqPF78EioEQlSOxViCuctEtnQuPcDLHNFr10byTZY9roObiqdsJLMVvb2Xl
> iJjAqaPa9AkYwGE6xHw2ispwg64Rse0+AtKups19WIU=
> -----END CERTIFICATE-----
> EOF
Dump an example certificate (example-leaf.crt)
$ certigo dump example-leaf.crt
** CERTIFICATE 1 **
Not Before: 2016-06-10 22:14:11 +0000 UTC
Not After : 2023-04-15 22:14:11 +0000 UTC
Subject: C=US, ST=CA, O=certigo, OU=example, CN=example-leaf
Issuer: C=US, ST=CA, O=certigo, OU=example, CN=example-leaf
Alternate DNS Names:
\tlocalhost (esc)
Alternate IP Addresses:
\t127.0.0.1 (esc)
\t::1 (esc)
+1 -1
View File
@@ -26,7 +26,7 @@ Set up test data.
Dump an example certificate (example-leaf.crt)
$ certigo dump example-leaf.crt
$ certigo --verbose dump example-leaf.crt
** CERTIFICATE 1 **
Serial: 15384458167827828543
Not Before: 2016-06-10 22:14:11 +0000 UTC
+1 -1
View File
@@ -58,7 +58,7 @@ Set up test data.
Dump PEM blocks from a PKCS12 keystore.
$ certigo dump --pem --password password example.p12
$ certigo --verbose dump --pem --password password example.p12
-----BEGIN CERTIFICATE-----
MIIDLDCCAhQCCQCa74bQsAj2/jANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJV
UzELMAkGA1UECBMCQ0ExEDAOBgNVBAoTB2NlcnRpZ28xEDAOBgNVBAsTB2V4YW1w
+1 -1
View File
@@ -19,7 +19,7 @@ Set up test data.
Dump an example certificate (example-leaf.crt)
$ certigo dump example-small-key.crt
$ certigo --verbose dump example-small-key.crt
** CERTIFICATE 1 **
Serial: 14381893493177441266
Not Before: 2016-06-10 22:14:12 +0000 UTC