From 297aa9246a39ab9e0c93b66a3d7b939b5a08cebe Mon Sep 17 00:00:00 2001 From: Christopher Denny Date: Mon, 6 Jun 2016 16:13:27 -0700 Subject: [PATCH 1/3] Added support to output alias info for jceks certs. GetCerts now returns an array of alias strings along with certs, the array contains empty strings if not jceks. DisplayCerts now takes in an alias string along with the cert and only prints it if non empty. --- display.go | 9 +++++++-- main.go | 35 ++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/display.go b/display.go index f74c372..158c481 100644 --- a/display.go +++ b/display.go @@ -20,6 +20,7 @@ import ( "bytes" "crypto/x509" "encoding/hex" + "fmt" "os" "strings" "text/template" @@ -54,10 +55,11 @@ Email Addresses: {{range .EmailAddresses}} Serial Number: {{.SerialNumber}} {{end}} ` -// displayCert takes in an x509 Certificate object and prints out relevant +// displayCert takes in an x509 Certificate object and an alias +// (for jckes 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 *x509.Certificate) { +func displayCert(cert *x509.Certificate, alias string) { funcMap := template.FuncMap{ "hexify": hexify, "certStart": certStart, @@ -65,6 +67,9 @@ func displayCert(cert *x509.Certificate) { } t := template.New("Cert template").Funcs(funcMap) t, _ = t.Parse(layout) + if alias != "" { + fmt.Println("Alias:", alias) + } t.Execute(os.Stdout, cert) } diff --git a/main.go b/main.go index 43deb14..297f9b1 100644 --- a/main.go +++ b/main.go @@ -56,7 +56,7 @@ func main() { os.Exit(1) } - certs, err := getCerts(*dumpFile, format) + certs, aliases, err := getCerts(*dumpFile, format) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) @@ -64,7 +64,7 @@ func main() { for i, cert := range certs { fmt.Println("CERTIFICATE", i+1) - displayCert(cert) + displayCert(cert, aliases[i]) fmt.Println() } } @@ -81,12 +81,14 @@ func formatForFile(filename, format string) (string, bool) { } // getCerts takes in a filename and format type and returns an -// array of all the certificates found in that file. If no format +// array of all the certificates found in that file along with aliases +// for each cert if the format of the input was jceks. If no format // is specified for the file, getCerts guesses what format was used // based on the file extension used in the file name. If it can't // guess based on this it returns and error. -func getCerts(file, format string) ([]*x509.Certificate, error) { +func getCerts(file, format string) ([]*x509.Certificate, []string, error) { var certs []*x509.Certificate + var aliases []string data, _ := ioutil.ReadFile(file) switch format { case "PEM": @@ -94,9 +96,10 @@ func getCerts(file, format string) ([]*x509.Certificate, error) { for block != nil { cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return nil, err + return nil, nil, err } certs = append(certs, cert) + aliases = append(aliases, "") block, data = pem.Decode(data) } case "PKCS12": @@ -105,15 +108,16 @@ func getCerts(file, format string) ([]*x509.Certificate, error) { password, _ := scanner.ReadString('\n') blocks, err := pkcs12.ToPEM(data, strings.TrimSuffix(password, "\n")) if err != nil { - return nil, err + return nil, nil, err } for _, block := range blocks { if block.Type == "CERTIFICATE" { cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return nil, err + return nil, nil, err } certs = append(certs, cert) + aliases = append(aliases, "") } } case "JCEKS": @@ -122,26 +126,31 @@ func getCerts(file, format string) ([]*x509.Certificate, error) { password, _ := scanner.ReadString('\n') keyStore, err := jceks.Load(file, []byte(strings.TrimSuffix(password, "\n"))) if err != nil { - return nil, err + return nil, nil, err } for _, alias := range keyStore.ListCerts() { cert, _ := keyStore.GetCert(alias) if err != nil { - return nil, err + return nil, nil, err } certs = append(certs, cert) + aliases = append(aliases, alias) } for _, alias := range keyStore.ListPrivateKeys() { fmt.Printf("Enter password for alias [%s]: ", alias) password, _ := scanner.ReadString('\n') _, certArr, err := keyStore.GetPrivateKeyAndCerts(alias, []byte(strings.TrimSuffix(password, "\n"))) if err != nil { - return nil, err + return nil, nil, err } - certs = append(certs, certArr...) + for _, cert := range certArr { + certs = append(certs, cert) + aliases = append(aliases, alias) + } + //certs = append(certs, certArr...) } default: - return nil, fmt.Errorf("unknown file type: %s", format) + return nil, nil, fmt.Errorf("unknown file type: %s", format) } - return certs, nil + return certs, aliases, nil } From 248a04a2344cc00f2f5847a7b0af2e78292f1b45 Mon Sep 17 00:00:00 2001 From: Christopher Denny Date: Tue, 7 Jun 2016 12:59:21 -0700 Subject: [PATCH 2/3] Cleaned up alias output. No longer uses separate arrays for certs and their aliases. Now both are contained in a single struct called CertWithAlias. An array of these are passed around instead of two separate arrays, one for certs and one for their aliases. --- display.go | 9 ++++----- main.go | 43 +++++++++++++++++++++---------------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/display.go b/display.go index 158c481..01fbc38 100644 --- a/display.go +++ b/display.go @@ -18,7 +18,6 @@ package main import ( "bytes" - "crypto/x509" "encoding/hex" "fmt" "os" @@ -59,7 +58,7 @@ Serial Number: {{.SerialNumber}} {{end}} // (for jckes 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 *x509.Certificate, alias string) { +func displayCert(cert CertWithAlias) { funcMap := template.FuncMap{ "hexify": hexify, "certStart": certStart, @@ -67,10 +66,10 @@ func displayCert(cert *x509.Certificate, alias string) { } t := template.New("Cert template").Funcs(funcMap) t, _ = t.Parse(layout) - if alias != "" { - fmt.Println("Alias:", alias) + if cert.alias != "" { + fmt.Println("Alias:", cert.alias) } - t.Execute(os.Stdout, cert) + t.Execute(os.Stdout, cert.cert) } diff --git a/main.go b/main.go index 297f9b1..21d51bb 100644 --- a/main.go +++ b/main.go @@ -47,6 +47,11 @@ var fileExtToFormat = map[string]string{ ".jceks": "JCEKS", } +type CertWithAlias struct { + alias string + cert *x509.Certificate +} + func main() { switch kingpin.MustParse(app.Parse(os.Args[1:])) { case dump.FullCommand(): // Dump certificate @@ -56,7 +61,7 @@ func main() { os.Exit(1) } - certs, aliases, err := getCerts(*dumpFile, format) + certs, err := getCerts(*dumpFile, format) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) os.Exit(1) @@ -64,7 +69,7 @@ func main() { for i, cert := range certs { fmt.Println("CERTIFICATE", i+1) - displayCert(cert, aliases[i]) + displayCert(cert) fmt.Println() } } @@ -86,9 +91,8 @@ func formatForFile(filename, format string) (string, bool) { // is specified for the file, getCerts guesses what format was used // based on the file extension used in the file name. If it can't // guess based on this it returns and error. -func getCerts(file, format string) ([]*x509.Certificate, []string, error) { - var certs []*x509.Certificate - var aliases []string +func getCerts(file, format string) ([]CertWithAlias, error) { + var certs []CertWithAlias data, _ := ioutil.ReadFile(file) switch format { case "PEM": @@ -96,10 +100,9 @@ func getCerts(file, format string) ([]*x509.Certificate, []string, error) { for block != nil { cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return nil, nil, err + return nil, err } - certs = append(certs, cert) - aliases = append(aliases, "") + certs = append(certs, CertWithAlias{cert: cert}) block, data = pem.Decode(data) } case "PKCS12": @@ -108,16 +111,15 @@ func getCerts(file, format string) ([]*x509.Certificate, []string, error) { password, _ := scanner.ReadString('\n') blocks, err := pkcs12.ToPEM(data, strings.TrimSuffix(password, "\n")) if err != nil { - return nil, nil, err + return nil, err } for _, block := range blocks { if block.Type == "CERTIFICATE" { cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return nil, nil, err + return nil, err } - certs = append(certs, cert) - aliases = append(aliases, "") + certs = append(certs, CertWithAlias{cert: cert}) } } case "JCEKS": @@ -126,31 +128,28 @@ func getCerts(file, format string) ([]*x509.Certificate, []string, error) { password, _ := scanner.ReadString('\n') keyStore, err := jceks.Load(file, []byte(strings.TrimSuffix(password, "\n"))) if err != nil { - return nil, nil, err + return nil, err } for _, alias := range keyStore.ListCerts() { cert, _ := keyStore.GetCert(alias) if err != nil { - return nil, nil, err + return nil, err } - certs = append(certs, cert) - aliases = append(aliases, alias) + certs = append(certs, CertWithAlias{cert: cert, alias: alias}) } for _, alias := range keyStore.ListPrivateKeys() { fmt.Printf("Enter password for alias [%s]: ", alias) password, _ := scanner.ReadString('\n') _, certArr, err := keyStore.GetPrivateKeyAndCerts(alias, []byte(strings.TrimSuffix(password, "\n"))) if err != nil { - return nil, nil, err + return nil, err } for _, cert := range certArr { - certs = append(certs, cert) - aliases = append(aliases, alias) + certs = append(certs, CertWithAlias{cert: cert, alias: alias}) } - //certs = append(certs, certArr...) } default: - return nil, nil, fmt.Errorf("unknown file type: %s", format) + return nil, fmt.Errorf("unknown file type: %s", format) } - return certs, aliases, nil + return certs, nil } From 01131ea73e4c834be1ae439d423ec104acdccd2b Mon Sep 17 00:00:00 2001 From: Christopher Denny Date: Tue, 7 Jun 2016 13:12:15 -0700 Subject: [PATCH 3/3] Made CertWithAlias type nonexportable. --- display.go | 2 +- main.go | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/display.go b/display.go index 01fbc38..8623764 100644 --- a/display.go +++ b/display.go @@ -58,7 +58,7 @@ Serial Number: {{.SerialNumber}} {{end}} // (for jckes 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 CertWithAlias) { +func displayCert(cert certWithAlias) { funcMap := template.FuncMap{ "hexify": hexify, "certStart": certStart, diff --git a/main.go b/main.go index 21d51bb..1019c76 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ var fileExtToFormat = map[string]string{ ".jceks": "JCEKS", } -type CertWithAlias struct { +type certWithAlias struct { alias string cert *x509.Certificate } @@ -91,8 +91,8 @@ func formatForFile(filename, format string) (string, bool) { // is specified for the file, getCerts guesses what format was used // based on the file extension used in the file name. If it can't // guess based on this it returns and error. -func getCerts(file, format string) ([]CertWithAlias, error) { - var certs []CertWithAlias +func getCerts(file, format string) ([]certWithAlias, error) { + var certs []certWithAlias data, _ := ioutil.ReadFile(file) switch format { case "PEM": @@ -102,7 +102,7 @@ func getCerts(file, format string) ([]CertWithAlias, error) { if err != nil { return nil, err } - certs = append(certs, CertWithAlias{cert: cert}) + certs = append(certs, certWithAlias{cert: cert}) block, data = pem.Decode(data) } case "PKCS12": @@ -119,7 +119,7 @@ func getCerts(file, format string) ([]CertWithAlias, error) { if err != nil { return nil, err } - certs = append(certs, CertWithAlias{cert: cert}) + certs = append(certs, certWithAlias{cert: cert}) } } case "JCEKS": @@ -135,7 +135,7 @@ func getCerts(file, format string) ([]CertWithAlias, error) { if err != nil { return nil, err } - certs = append(certs, CertWithAlias{cert: cert, alias: alias}) + certs = append(certs, certWithAlias{cert: cert, alias: alias}) } for _, alias := range keyStore.ListPrivateKeys() { fmt.Printf("Enter password for alias [%s]: ", alias) @@ -145,7 +145,7 @@ func getCerts(file, format string) ([]CertWithAlias, error) { return nil, err } for _, cert := range certArr { - certs = append(certs, CertWithAlias{cert: cert, alias: alias}) + certs = append(certs, certWithAlias{cert: cert, alias: alias}) } } default: