package inspect import ( "crypto/rsa" "crypto/x509" "errors" ) // DERCSRInfo attempts to parse a DER-form X.509 CSR and returns information // about it. func DERCSRInfo(loc string, der []byte) Info { csr, err := x509.ParseCertificateRequest(der) if err != nil { return &BadInfo{ Typ: TypeX509CSR, Loc: loc, Underlying: err, } } return CSRInfo(loc, csr) } // CSRInfo returns information about a CSR. Note it holds a reference to the // csr argument. func CSRInfo(loc string, csr *x509.CertificateRequest) Info { key, ok := csr.PublicKey.(*rsa.PublicKey) if !ok { return &BadInfo{ Typ: TypeX509CSR, Loc: loc, Underlying: errors.New("CSR public key is not RSA"), } } return &CSR{ Loc: loc, CSR: csr, Public: PublicKeyInfo(loc, key), } } // CSR holds structured information about a CSR. It implements Info. type CSR struct { // Loc is the location the CSR was encountered. Loc string // CSR is the raw CSR. CSR *x509.CertificateRequest // Public holds information about the public portion of the key. Public *PublicKey } // Type indicates this is a private key. func (csr *CSR) Type() Type { return TypeX509CSR } // Location returns the location data stored by PrivateKeyInfo. func (csr *CSR) Location() string { return csr.Loc } // Info returns structured information about the prvate key. func (csr *CSR) Info() []Section { return []Section{ csr.SubjectSection(), csr.Public.PublicKeyInfoSection(), } } // SubjectSection returns information about the subject. func (csr *CSR) SubjectSection() Section { f := []Field{ Field{ Key: "Description", Value: csr.CSR.Subject.CommonName, }, } f = appendX509DNField(f, csr.CSR.Subject) if len(csr.CSR.DNSNames) > 0 { f = append(f, Field{ Key: "Hostnames", Value: csr.CSR.DNSNames, }) } if len(csr.CSR.IPAddresses) > 0 { var ips []string for _, ip := range csr.CSR.IPAddresses { ips = append(ips, ip.String()) } f = append(f, Field{ Key: "IP addresses", Value: ips, }) } return Section{ Title: "Subject", Fields: f, } }