diff --git a/cert_encoder.go b/encoder.go similarity index 91% rename from cert_encoder.go rename to encoder.go index da6ec09..7e7fb34 100644 --- a/cert_encoder.go +++ b/encoder.go @@ -10,7 +10,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "math/big" "net" "strconv" "strings" @@ -61,7 +60,7 @@ var algoName = [...]string{ type basicConstraints struct { IsCA bool `json:"is_ca"` - MaxPathLen int `json:"pathlen"` + MaxPathLen *int `json:"pathlen,omitempty"` } type nameConstraints struct { @@ -71,7 +70,7 @@ type nameConstraints struct { type simpleCertificate struct { Alias string `json:"alias,omitempty"` - SerialNumber *big.Int `json:"serial"` + SerialNumber string `json:"serial"` NotBefore time.Time `json:"not_before"` NotAfter time.Time `json:"not_after"` SignatureAlgorithm simpleSigAlg `json:"signature_algorithm"` @@ -82,15 +81,15 @@ type simpleCertificate struct { NameConstraints nameConstraints `json:"name_constraints"` KeyUsage simpleKeyUsage `json:"key_usage,omitempty"` ExtKeyUsage []simpleExtKeyUsage `json:"extended_key_usage,omitempty"` - AltDNSNames []string `json:"alternate_dns_names,omitempty"` - AltIPAddresses []net.IP `json:"alternate_ip_addresses,omitempty"` + AltDNSNames []string `json:"dns_names,omitempty"` + AltIPAddresses []net.IP `json:"ip_addresses,omitempty"` EmailAddresses []string `json:"email_addresses,omitempty"` Warnings []string `json:"warnings,omitempty"` } type simplePkixName struct { Name pkix.Name - KeyId []byte + KeyID []byte } type simpleKeyUsage x509.KeyUsage @@ -106,26 +105,18 @@ type simpleResult struct { func createSimpleCertificate(c certWithName) simpleCertificate { out := simpleCertificate{ Alias: c.name, - SerialNumber: c.cert.SerialNumber, + SerialNumber: c.cert.SerialNumber.String(), NotBefore: c.cert.NotBefore, NotAfter: c.cert.NotAfter, SignatureAlgorithm: simpleSigAlg(c.cert.SignatureAlgorithm), IsSelfSigned: isSelfSigned(c.cert), Subject: simplePkixName{ Name: c.cert.Subject, - KeyId: c.cert.SubjectKeyId, + KeyID: c.cert.SubjectKeyId, }, Issuer: simplePkixName{ Name: c.cert.Issuer, - KeyId: c.cert.AuthorityKeyId, - }, - BasicConstraints: basicConstraints{ - IsCA: c.cert.IsCA, - MaxPathLen: c.cert.MaxPathLen, - }, - NameConstraints: nameConstraints{ - Critical: c.cert.PermittedDNSDomainsCritical, - PermittedDNSDomains: c.cert.PermittedDNSDomains, + KeyID: c.cert.AuthorityKeyId, }, KeyUsage: simpleKeyUsage(c.cert.KeyUsage), AltDNSNames: c.cert.DNSNames, @@ -133,6 +124,23 @@ func createSimpleCertificate(c certWithName) simpleCertificate { EmailAddresses: c.cert.EmailAddresses, Warnings: certWarnings(c.cert), } + + if c.cert.BasicConstraintsValid { + out.BasicConstraints = basicConstraints{ + IsCA: c.cert.IsCA, + } + if c.cert.MaxPathLen > 0 || c.cert.MaxPathLenZero { + out.BasicConstraints.MaxPathLen = &c.cert.MaxPathLen + } + } + + if len(c.cert.PermittedDNSDomains) > 0 { + out.NameConstraints = nameConstraints{ + Critical: c.cert.PermittedDNSDomainsCritical, + PermittedDNSDomains: c.cert.PermittedDNSDomains, + } + } + simpleEku := []simpleExtKeyUsage{} for _, eku := range c.cert.ExtKeyUsage { simpleEku = append(simpleEku, simpleExtKeyUsage(eku)) @@ -157,7 +165,7 @@ func (p simplePkixName) MarshalJSON() ([]byte, error) { out["organization"] = p.Name.Organization } if len(p.Name.OrganizationalUnit) > 0 { - out["organization_unit"] = p.Name.OrganizationalUnit + out["organizational_unit"] = p.Name.OrganizationalUnit } if len(p.Name.Country) > 0 { out["country"] = p.Name.Country @@ -165,8 +173,8 @@ func (p simplePkixName) MarshalJSON() ([]byte, error) { if len(p.Name.Locality) > 0 { out["locality"] = p.Name.Locality } - if len(p.KeyId) > 0 { - out["key_id"] = hexify(p.KeyId) + if len(p.KeyID) > 0 { + out["key_id"] = hexify(p.KeyID) } return json.Marshal(out) diff --git a/main.go b/main.go index 937cb0a..f4f9be4 100644 --- a/main.go +++ b/main.go @@ -50,14 +50,14 @@ var ( dumpType = dump.Flag("format", "Format of given input (PEM, DER, JCEKS, PKCS12; heuristic if missing).").String() dumpPem = dump.Flag("pem", "Write output as PEM blocks instead of human-readable format.").Bool() dumpPassword = dump.Flag("password", "Password for PKCS12/JCEKS key stores (if required).").String() - dumpJson = dump.Flag("json", "Write output as machine-readable JSON format.").Bool() + dumpJSON = dump.Flag("json", "Write output as machine-readable JSON format.").Bool() connect = app.Command("connect", "Connect to a server and print its certificate(s).") connectTo = connect.Arg("server:port", "Hostname or IP to connect to.").String() connectName = connect.Flag("name", "Override the server name used for Server Name Indication (SNI).").String() connectCaPath = connect.Flag("ca", "Path to CA bundle (system default if unspecified).").ExistingFile() connectPem = connect.Flag("pem", "Write output as PEM blocks instead of human-readable format.").Bool() - connectJson = connect.Flag("json", "Write output as machine-readable JSON format.").Bool() + connectJSON = connect.Flag("json", "Write output as machine-readable JSON format.").Bool() verify = app.Command("verify", "Verify a certificate chain from file/stdin against a name.") verifyFile = verify.Arg("file", "Certificate file to dump (or stdin if not specified).").ExistingFile() @@ -117,7 +117,7 @@ func main() { } }) - if *dumpJson { + if *dumpJSON { blob, _ := json.Marshal(result) fmt.Println(string(blob)) } else { @@ -158,7 +158,7 @@ func main() { result.VerifyResult = &verifyResult } - if *connectJson { + if *connectJSON { blob, _ := json.Marshal(result) fmt.Println(string(blob)) } else { diff --git a/verify.go b/verify.go index aadd3a3..e1136fd 100644 --- a/verify.go +++ b/verify.go @@ -29,13 +29,9 @@ type simpleVerifyCert struct { SignatureAlgorithm simpleSigAlg `json:"signature_algorithm"` } -type simpleVerifyChain struct { - Certs []simpleVerifyCert `json:"chain"` -} - type simpleVerification struct { - Error string `json:"error,omitempty"` - Chains []simpleVerifyChain `json:"chains"` + Error string `json:"error,omitempty"` + Chains [][]simpleVerifyCert `json:"chains"` } func caBundle(caPath string) *x509.CertPool { @@ -76,7 +72,7 @@ func verifyChain(certs []*x509.Certificate, dnsName, caPath string) simpleVerifi //green.Printf("Server certificates appear to be valid (found %d chains):\n", len(chains)) for _, chain := range chains { - aChain := simpleVerifyChain{} + aChain := []simpleVerifyCert{} for _, cert := range chain { aCert := simpleVerifyCert{} if cert.Subject.CommonName != "" { @@ -86,7 +82,7 @@ func verifyChain(certs []*x509.Certificate, dnsName, caPath string) simpleVerifi } aCert.IsSelfSigned = isSelfSigned(cert) aCert.SignatureAlgorithm = simpleSigAlg(cert.SignatureAlgorithm) - aChain.Certs = append(aChain.Certs, aCert) + aChain = append(aChain, aCert) } result.Chains = append(result.Chains, aChain) } @@ -114,8 +110,8 @@ func printVerifyResult(result simpleVerification) { return } for i, chain := range result.Chains { - fmt.Printf("[%d] %s\n", i, fmtCert(chain.Certs[0])) - for j, cert := range chain.Certs { + fmt.Printf("[%d] %s\n", i, fmtCert(chain[0])) + for j, cert := range chain { if j == 0 { continue }