// certSigAlgScan returns the server certificate with various ciphers in the ClientHello func certSigAlgsScanByCipher(addr, hostname string) (grade Grade, output Output, err error) { var certSigAlgs = make(map[string]string) for cipherID := range tls.CipherSuites { _, _, derCerts, e := sayHello(addr, hostname, []uint16{cipherID}, nil, tls.VersionTLS12, []tls.SignatureAndHash{}) if e == nil { if len(derCerts) == 0 { return Bad, nil, errors.New("no certs returned") } certs, _, err := helpers.ParseCertificatesDER(derCerts[0], "") if err != nil { return Bad, nil, err } certSigAlgs[tls.CipherSuites[cipherID].Name] = helpers.SignatureString(certs[0].SignatureAlgorithm) //certSigAlgs = append(certSigAlgs, certs[0].SignatureAlgorithm) } } if len(certSigAlgs) > 0 { grade = Good output = certSigAlgs } else { err = errors.New("no cipher supported") } return }
// certSigAlgScan returns the server certificate with various sigature and hash algorithms in the ClientHello func certSigAlgsScan(addr, hostname string) (grade Grade, output Output, err error) { var certSigAlgs = make(map[string]string) for _, sigAlg := range tls.AllSignatureAndHashAlgorithms { _, _, derCerts, e := sayHello(addr, hostname, nil, nil, tls.VersionTLS12, []tls.SignatureAndHash{sigAlg}) if e == nil { if len(derCerts) == 0 { return Bad, nil, errors.New("no certs returned") } certs, _, err := helpers.ParseCertificatesDER(derCerts[0], "") if err != nil { return Bad, nil, err } certSigAlgs[sigAlg.String()] = helpers.SignatureString(certs[0].SignatureAlgorithm) //certSigAlgs = append(certSigAlgs, certs[0].SignatureAlgorithm) } } if len(certSigAlgs) > 0 { grade = Good output = certSigAlgs } else { err = errors.New("no SigAlgs supported") } return }
// MarshalJSON serialises the bundle to JSON. The resulting JSON // structure contains the bundle (as a sequence of PEM-encoded // certificates), the certificate, the private key, the size of they // key, the issuer(s), the subject name(s), the expiration, the // hostname(s), the OCSP server, and the signature on the certificate. func (b *Bundle) MarshalJSON() ([]byte, error) { if b == nil || b.Cert == nil { return nil, errors.New("no certificate in bundle") } var keyBytes, rootBytes []byte var keyLength int var typeString string var keyType string keyLength = helpers.KeyLength(b.Cert.PublicKey) switch b.Cert.PublicKeyAlgorithm { case x509.ECDSA: keyType = fmt.Sprintf("%d-bit ECDSA", keyLength) case x509.RSA: keyType = fmt.Sprintf("%d-bit RSA", keyLength) case x509.DSA: keyType = "DSA" default: keyType = "Unknown" } if rsaKey, ok := b.Key.(*rsa.PrivateKey); ok { keyBytes = x509.MarshalPKCS1PrivateKey(rsaKey) typeString = "RSA PRIVATE KEY" } else if ecdsaKey, ok := b.Key.(*ecdsa.PrivateKey); ok { keyBytes, _ = x509.MarshalECPrivateKey(ecdsaKey) typeString = "EC PRIVATE KEY" } if len(b.Hostnames) == 0 { b.buildHostnames() } var ocspSupport = false if b.Cert.OCSPServer != nil { ocspSupport = true } var crlSupport = false if b.Cert.CRLDistributionPoints != nil { crlSupport = true } if b.Root != nil { rootBytes = b.Root.Raw } return json.Marshal(map[string]interface{}{ "bundle": chain(b.Chain), "root": PemBlockToString(&pem.Block{Type: "CERTIFICATE", Bytes: rootBytes}), "crt": PemBlockToString(&pem.Block{Type: "CERTIFICATE", Bytes: b.Cert.Raw}), "key": PemBlockToString(&pem.Block{Type: typeString, Bytes: keyBytes}), "key_type": keyType, "key_size": keyLength, "issuer": names(b.Issuer.Names), "subject": names(b.Subject.Names), "expires": b.Expires, "hostnames": b.Hostnames, "ocsp_support": ocspSupport, "crl_support": crlSupport, "ocsp": b.Cert.OCSPServer, "signature": helpers.SignatureString(b.Cert.SignatureAlgorithm), "status": b.Status, }) }
// ParseCertificate parses an x509 certificate. func ParseCertificate(cert *x509.Certificate) *Certificate { c := &Certificate{ RawPEM: string(helpers.EncodeCertificatePEM(cert)), SignatureAlgorithm: helpers.SignatureString(cert.SignatureAlgorithm), NotBefore: cert.NotBefore, NotAfter: cert.NotAfter, Subject: ParseName(cert.Subject), SANs: cert.DNSNames, } for _, ip := range cert.IPAddresses { c.SANs = append(c.SANs, ip.String()) } return c }
// ParseCertificate parses an x509 certificate. func ParseCertificate(cert *x509.Certificate) *Certificate { c := &Certificate{ RawPEM: string(helpers.EncodeCertificatePEM(cert)), SignatureAlgorithm: helpers.SignatureString(cert.SignatureAlgorithm), NotBefore: cert.NotBefore, NotAfter: cert.NotAfter, Subject: ParseName(cert.Subject), Issuer: ParseName(cert.Issuer), SANs: cert.DNSNames, AKI: formatKeyID(cert.AuthorityKeyId), SKI: formatKeyID(cert.SubjectKeyId), SerialNumber: cert.SerialNumber.String(), } for _, ip := range cert.IPAddresses { c.SANs = append(c.SANs, ip.String()) } return c }
// Applies the naming convention of "commonname_issuedate_sigalg.crt" to all // files by renaming them using helpers.ParseCertificatePEM func applyNamingConv(file []byte, filename string) error { // Get the certificate info from helpers.ParseCertificatePEM response, err := helpers.ParseCertificatePEM(file) if err != nil { fmt.Println(err) return err } // Generate the name of the file name := "" // If CommonName field is empty, then use the Organization name instead if len(response.Subject.CommonName) == 0 { name = strings.Replace(response.Subject.Organization[0], " ", "", -1) name = strings.Replace(name, "/", "-", -1) } else { name = strings.Replace(response.Subject.CommonName, " ", "", -1) name = strings.Replace(name, "/", "-", -1) } dateIssued := fmt.Sprintf("%d-%d-%d", response.NotBefore.Year(), int(response.NotBefore.Month()), response.NotBefore.Day()) name += "_" + dateIssued + "_" + helpers.SignatureString(response.SignatureAlgorithm) // If there is already a certificate of the same name, then add a count // at the end AKA, "commonname_issuedate_sigalg_2.crt" if there is // already a "commonname_issuedate_sigalg.crt", etc... filenameCount[name]++ if filenameCount[name] > 1 { name += "_" + strconv.Itoa(filenameCount[name]) } // Finally, rename the file err = os.Rename(*directory+"/"+filename, *directory+"/"+name+".crt") if err != nil { return err } return nil }