func pkixNameToString(name *pkix.Name) string { seq := name.ToRDNSequence() var s bytes.Buffer for _, rdnSet := range seq { for _, rdn := range rdnSet { if s.Len() != 0 { s.WriteString(",") } key := "" t := rdn.Type if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { switch t[3] { case 3: key = "cn" case 5: key = "serial" case 6: key = "c" case 7: key = "l" case 10: key = "o" case 11: key = "ou" } } if key == "" { key = t.String() } s.WriteString(fmt.Sprintf("%v=%v", key, rdn.Value)) } } return s.String() }
// signPKCS7 does the minimal amount of work necessary to embed an RSA // signature into a PKCS#7 certificate. // // We prepare the certificate using the x509 package, read it back in // to our custom data type and then write it back out with the signature. func signPKCS7(rand io.Reader, priv *rsa.PrivateKey, msg []byte) ([]byte, error) { const serialNumber = 0x5462c4dd // arbitrary name := pkix.Name{CommonName: "gomobile"} template := &x509.Certificate{ SerialNumber: big.NewInt(serialNumber), SignatureAlgorithm: x509.SHA1WithRSA, Subject: name, } b, err := x509.CreateCertificate(rand, template, template, priv.Public(), priv) if err != nil { return nil, err } c := certificate{} if _, err := asn1.Unmarshal(b, &c); err != nil { return nil, err } h := sha1.New() h.Write(msg) hashed := h.Sum(nil) signed, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, hashed) if err != nil { return nil, err } content := pkcs7SignedData{ ContentType: oidSignedData, Content: signedData{ Version: 1, DigestAlgorithms: []pkix.AlgorithmIdentifier{{ Algorithm: oidSHA1, Parameters: asn1.RawValue{Tag: 5}, }}, ContentInfo: contentInfo{Type: oidData}, Certificates: c, SignerInfos: []signerInfo{{ Version: 1, IssuerAndSerialNumber: issuerAndSerialNumber{ Issuer: name.ToRDNSequence(), SerialNumber: serialNumber, }, DigestAlgorithm: pkix.AlgorithmIdentifier{ Algorithm: oidSHA1, Parameters: asn1.RawValue{Tag: 5}, }, DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{ Algorithm: oidRSAEncryption, Parameters: asn1.RawValue{Tag: 5}, }, EncryptedDigest: signed, }}, }, } return asn1.Marshal(content) }
// Name returns the PKIX name for the request. func (cr *CertificateRequest) Name() pkix.Name { var name pkix.Name name.CommonName = cr.CN for _, n := range cr.Names { appendIf(n.C, &name.Country) appendIf(n.ST, &name.Province) appendIf(n.L, &name.Locality) appendIf(n.O, &name.Organization) appendIf(n.OU, &name.OrganizationalUnit) } return name }
// Name returns the PKIX name for the subject. func (s *Subject) Name() pkix.Name { var name pkix.Name name.CommonName = s.CN for _, n := range s.Names { appendIf(n.C, &name.Country) appendIf(n.ST, &name.Province) appendIf(n.L, &name.Locality) appendIf(n.O, &name.Organization) appendIf(n.OU, &name.OrganizationalUnit) } return name }
func parseDN(dn string) *pkix.Name { name := pkix.Name{} matches := dnRegexp.FindAllStringSubmatch(dn, -1) for _, match := range matches { val := match[2] if val == "" { continue } switch match[1] { case "C": name.Country = append(name.Country, val) case "O": name.Organization = append(name.Organization, val) case "OU": name.OrganizationalUnit = append(name.OrganizationalUnit, val) case "L": name.Locality = append(name.Locality, val) case "ST": name.Province = append(name.Province, val) case "SN": name.SerialNumber = val case "CN": name.CommonName = val } } return &name }
func (info *HostCertificateInfo) toName(s string) *pkix.Name { var name pkix.Name for _, pair := range strings.Split(s, ",") { attr := strings.SplitN(pair, "=", 2) if len(attr) != 2 { continue } v := attr[1] switch strings.ToLower(attr[0]) { case "cn": name.CommonName = v case "ou": name.OrganizationalUnit = append(name.OrganizationalUnit, v) case "o": name.Organization = append(name.Organization, v) case "l": name.Locality = append(name.Locality, v) case "st": name.Province = append(name.Province, v) case "c": name.Country = append(name.Country, v) case "emailaddress": name.Names = append(name.Names, pkix.AttributeTypeAndValue{Type: emailAddressOID, Value: v}) } } return &name }
func createBundle(c *cli.Context) { if !c.Args().Present() { cli.ShowSubcommandHelp(c) log.Fatalf("Usage: %v name (common name defaults to name, use --cn and "+ "different name if you need multiple certs for same cn)", c.Command.FullName()) } commonName := strings.Join(c.Args()[:], " ") var filename string if filename = c.String("filename"); len(filename) == 0 { filename = strings.Replace(commonName, " ", "_", -1) filename = strings.Replace(filename, "*", "wildcard", -1) } subject := pkix.Name{CommonName: commonName} if str := c.String("organization"); len(str) > 0 { subject.Organization = []string{str} } if str := c.String("locality"); len(str) > 0 { subject.Locality = []string{str} } if str := c.String("country"); len(str) > 0 { subject.Country = []string{str} } if str := c.String("province"); len(str) > 0 { subject.Province = []string{str} } if str := c.String("organizational-unit"); len(str) > 0 { subject.OrganizationalUnit = []string{str} } template := &x509.Certificate{ Subject: subject, NotAfter: time.Now().AddDate(0, 0, c.Int("expire")), } if c.Bool("ca") { template.IsCA = true filename = "ca" } else if c.Bool("client") { template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageClientAuth) template.EmailAddresses = c.StringSlice("email") } else { // We default to server template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageServerAuth) IPs := make([]net.IP, 0, len(c.StringSlice("ip"))) for _, ipStr := range c.StringSlice("ip") { if i := net.ParseIP(ipStr); i != nil { IPs = append(IPs, i) } } template.IPAddresses = IPs template.DNSNames = c.StringSlice("dns") } err := easypki.GenerateCertifcate(c.GlobalString("root"), filename, template) if err != nil { log.Fatal(err) } }
func prepareName(name *pkix.Name) { if name.Country == nil { name.StreetAddress = []string{""} name.PostalCode = []string{""} name.Province = []string{""} name.Locality = []string{""} name.OrganizationalUnit = []string{""} name.Organization = []string{""} name.Country = []string{""} } }
func parsePkixName(s string) (*pkix.Name, error) { name := new(pkix.Name) tokens := strings.Split(s, ",") for _, token := range tokens { token = strings.TrimSpace(token) kv := strings.SplitN(token, "=", 2) if len(kv) != 2 { return nil, fmt.Errorf("unrecognized token (expected k=v): %q", token) } k := strings.ToLower(kv[0]) v := kv[1] switch k { case "cn": name.CommonName = v default: return nil, fmt.Errorf("unrecognized key %q in token %q", k, token) } } return name, nil }
func Unmarshal(dn string) (pkix.Name, error) { var output pkix.Name segments := strings.Split(dn, ",") for segment := range segments { identifier := strings.SplitN(segments[segment], "=", 2) if identifier[0] == "CN" { output.CommonName = identifier[1] } else if identifier[0] == "C" { output.Country = append(output.Country, identifier[1]) } else if identifier[0] == "L" { output.Locality = append(output.Locality, identifier[1]) } else if identifier[0] == "ST" { output.Province = append(output.Province, identifier[1]) } else if identifier[0] == "SA" { output.StreetAddress = append(output.StreetAddress, identifier[1]) } else if identifier[0] == "O" { output.Organization = append(output.Organization, identifier[1]) } else if identifier[0] == "OU" { output.OrganizationalUnit = append(output.OrganizationalUnit, identifier[1]) } } return output, nil }
// Name returns the subject info as a PKIX name strucutre for a // certificate. func (si *SubjectInfo) Name() pkix.Name { var name pkix.Name if si.Country != "" { name.Country = []string{si.Country} } if si.OrgName != "" { name.Organization = []string{si.OrgName} } if si.OrgUnitName != "" { name.OrganizationalUnit = []string{si.OrgUnitName} } if si.Locality != "" { name.Locality = []string{si.Locality} } if si.StateOrProvince != "" { name.Province = []string{si.StateOrProvince} } if si.CommonName != "" { name.CommonName = si.CommonName } if si.Email != "" { name.Names = []pkix.AttributeTypeAndValue{ pkix.AttributeTypeAndValue{ Type: asn1EmailAddress, Value: si.Email, }, } } return name }
// GenerateKeys initializes a new tls key, confirms certificate details with the // user, obtains a signed certificate from the default ca, and stores the // resulting keys and certificates in kdir. This is meant to be called from // user-facing apps. func GenerateKeys(name *pkix.Name, addr, kdir string) *tao.Keys { host, _, err := net.SplitHostPort(addr) options.FailIf(err, "bad address: %s", addr) name.CommonName = host if ConfirmNames { fmt.Printf(""+ "Initializing fresh HTTP/TLS server key. Provide the following information,\n"+ "to be include in a CA-signed x509 certificate. Leave the response blank to\n"+ "accept the default value.\n\n"+ "The key and certificates will be stored in:\n %s\n\n", kdir) name = ConfirmName(name) } keys, err := tao.InitOnDiskTaoSealedKeys(tao.Signing, name, tao.Parent(), kdir, tao.SealPolicyDefault) options.FailIf(err, "can't create tao-sealed HTTPS/TLS keys") csr := NewCertificateSigningRequest(keys.VerifyingKey, name) SubmitAndInstall(keys, csr) return keys }
// Store a passed CSR to be signed func (c Project) SaveCSR(id int, csr *models.CertificateRequest) revel.Result { var user *models.User if c.RenderArgs["user"] == nil { c.Flash.Error("You must log in first") return c.Redirect(routes.App.Index()) } user = c.RenderArgs["user"].(*models.User) project := c.getProject(id) if project == nil { c.Flash.Error("Unable to access project") return c.Redirect(routes.Admin.Index()) } project_members := c.getProjectUsers(id) isMember := false for _, member := range project_members { if member.Id == user.Id { isMember = true } } if !user.IsAdmin && !isMember { c.Flash.Error("You do not have permissions for this page") return c.Redirect(routes.Admin.Index()) } csr.Project = project csr.User = user csr.CSR = []byte(c.Params.Values["csr.CSR"][0]) cas := c.getProjectCAs(project) for _, ca := range cas { if csr.RequestedCAId == ca.Id { csr.RequestedCA = ca break } } if csr.RequestedCA == nil { c.Flash.Error("Error finding requested CA") return c.Redirect(routes.Project.LoadCSR(id)) } block, _ := pem.Decode(csr.CSR) if block == nil { c.Flash.Error("Error PEM decoding CSR") return c.Redirect(routes.Project.LoadCSR(id)) } parsed_csr, err := ParseCertificationRequest(block.Bytes) if err != nil { c.Flash.Error("Error Decoding CSR") return c.Redirect(routes.Project.LoadCSR(id)) } var out pkix.Name var subject pkix.RDNSequence if _, err := asn1.Unmarshal(parsed_csr.CertificationRequestInfo.Subject.FullBytes, &subject); err != nil { c.Flash.Error(err.Error()) return c.Redirect(routes.Project.LoadCSR(id)) } out.FillFromRDNSequence(&subject) //If we get to this point we were successfully able to parse the CSR // Save CSR to database err = c.Txn.Insert(csr) if err != nil { c.Flash.Error("Error saving CSR", err.Error()) return c.Redirect(routes.Project.LoadCSR(id)) } c.Flash.Success("Submitted CSR for signing") return c.Redirect(routes.Project.Index(id)) }
func certNew(argv map[string]interface{}) (err error) { // TODO - this whole function needs to be refactored name := ArgString(argv["<name>"], nil) exportFile := ArgString(argv["--export"], nil) expiry := ArgInt(argv["--expiry"], 365) caName := ArgString(argv["--ca"], "") dnLocality := ArgString(argv["--dn-l"], "") dnState := ArgString(argv["--dn-st"], "") dnOrg := ArgString(argv["--dn-o"], "") dnOrgUnit := ArgString(argv["--dn-ou"], "") dnCountry := ArgString(argv["--dn-c"], "") dnStreet := ArgString(argv["--dn-street"], "") dnPostal := ArgString(argv["--dn-postal"], "") // TODO - This should really be in a certificate function subject := pkix.Name{CommonName: name} if dnLocality != "" { subject.Locality = []string{dnLocality} } if dnState != "" { subject.Province = []string{dnState} } if dnOrg != "" { subject.Organization = []string{dnOrg} } if dnOrgUnit != "" { subject.OrganizationalUnit = []string{dnOrgUnit} } if dnCountry != "" { subject.Country = []string{dnCountry} } if dnStreet != "" { subject.StreetAddress = []string{dnStreet} } if dnPostal != "" { subject.PostalCode = []string{dnPostal} } cert, err := x509.NewCertificate(nil) checkAppFatal("Couldn't create new certificate: %s", err) cert.Data.Body.Name = name cert.Data.Body.Expiry = expiry var files []ExportFile certFile := fmt.Sprintf("%s-cert.pem", cert.Data.Body.Name) keyFile := fmt.Sprintf("%s-key.pem", cert.Data.Body.Name) caFile := fmt.Sprintf("%s-cacert.pem", cert.Data.Body.Name) if caName == "" { // Self-signed err := cert.Generate(nil, &subject) checkAppFatal("Couldn't generate certificate: %s", err) files = append(files, ExportFile{Name: caFile, Mode: 0644, Content: []byte(cert.Data.Body.Certificate)}) } else { app := NewAdminApp() app.Load() app.LoadOrgIndex() caId, err := app.index.org.GetCA(caName) checkUserFatal("Couldn't find CA '%s'%.0s", caName, err) caContainerJson, err := app.fs.api.GetPrivate(app.entities.org.Data.Body.Id, caId) caContainer, err := document.NewContainer(caContainerJson) checkAppFatal("Couldn't create container from json: %s", err) caJson, err := app.entities.org.VerifyThenDecrypt(caContainer) checkAppFatal("Couldn't verify and decrypt ca container: %s", err) ca, err := x509.NewCA(caJson) checkAppFatal("Couldn't create ca: %s", err) err = cert.Generate(ca, &subject) checkAppFatal("Couldn't generate certificate: %s", err) files = append(files, ExportFile{Name: caFile, Mode: 0644, Content: []byte(ca.Data.Body.Certificate)}) } files = append(files, ExportFile{Name: certFile, Mode: 0644, Content: []byte(cert.Data.Body.Certificate)}) files = append(files, ExportFile{Name: keyFile, Mode: 0600, Content: []byte(cert.Data.Body.PrivateKey)}) if caName == "" { } else { } logger.Infof("Export to '%s'", exportFile) Export(files, exportFile) return nil }
func (cont *CSRController) New(params *CSRParams) (*x509.CSR, error) { logger.Debug("creating new CSR") logger.Tracef("received params: %s", params) if err := params.ValidateName(true); err != nil { return nil, err } if err := cont.env.LoadAdminEnv(); err != nil { return nil, err } // TODO - This should really be in a CSR function subject := pkix.Name{CommonName: *params.Name} if *params.DnLocality != "" { subject.Locality = []string{*params.DnLocality} } if *params.DnState != "" { subject.Province = []string{*params.DnState} } if *params.DnOrg != "" { subject.Organization = []string{*params.DnOrg} } if *params.DnOrgUnit != "" { subject.OrganizationalUnit = []string{*params.DnOrgUnit} } if *params.DnCountry != "" { subject.Country = []string{*params.DnCountry} } if *params.DnStreet != "" { subject.StreetAddress = []string{*params.DnStreet} } if *params.DnPostal != "" { subject.PostalCode = []string{*params.DnPostal} } logger.Debug("creating CSR struct") csr, err := x509.NewCSR(nil) if err != nil { return nil, err } csr.Data.Body.Id = x509.NewID() csr.Data.Body.Name = *params.Name if *params.CsrFile == "" && *params.KeyFile == "" { csr.Data.Body.KeyType = *params.KeyType logger.Debug("generating CSR and key") csr.Generate(&subject) } else { if *params.CsrFile == "" { return nil, fmt.Errorf("CSR PEM file must be provided if importing") } logger.Debugf("importing CSR from '%s'", *params.CsrFile) ok, err := fs.Exists(*params.CsrFile) if err != nil { return nil, err } if !ok { logger.Warnf("CSR file '%s' does not exist", *params.CsrFile) logger.Tracef("returning nil error") return nil, nil } logger.Debug("reading file") csrPem, err := fs.ReadFile(*params.CsrFile) if err != nil { return nil, err } logger.Debug("decoding CSR PEM") _, err = x509.PemDecodeX509CSR([]byte(csrPem)) if err != nil { return nil, err } csr.Data.Body.CSR = csrPem if *params.KeyFile != "" { logger.Debugf("importing private key file from '%s'", *params.KeyFile) ok, err := fs.Exists(*params.KeyFile) if err != nil { return nil, err } if !ok { logger.Warnf("key file '%s' does not exist", *params.KeyFile) logger.Trace("returning nil error") return nil, nil } logger.Debugf("reading key file") keyPem, err := fs.ReadFile(*params.KeyFile) if err != nil { return nil, err } logger.Debug("decoding private key PEM") key, err := crypto.PemDecodePrivate([]byte(keyPem)) if err != nil { return nil, err } keyType, err := crypto.GetKeyType(key) if err != nil { return nil, err } csr.Data.Body.KeyType = string(keyType) csr.Data.Body.PrivateKey = keyPem } } if *params.StandaloneFile == "" { err = cont.SaveCSR(csr) if err != nil { return nil, err } var tags string if *params.Tags == "NAME" { tags = *params.Name } else { tags = *params.Tags } err = cont.AddCSRToOrgIndex(csr, tags) if err != nil { return nil, err } } return csr, nil }
func (cont *CertificateController) New(params *CertificateParams) (*x509.Certificate, *x509.CA, error) { logger.Debug("creating new certificate") logger.Tracef("received params: %s", params) if err := params.ValidateName(true); err != nil { return nil, nil, err } if err := cont.env.LoadAdminEnv(); err != nil { return nil, nil, err } // TODO - This should really be in a certificate function subject := pkix.Name{CommonName: *params.Name} if *params.DnLocality != "" { subject.Locality = []string{*params.DnLocality} } if *params.DnState != "" { subject.Province = []string{*params.DnState} } if *params.DnOrg != "" { subject.Organization = []string{*params.DnOrg} } if *params.DnOrgUnit != "" { subject.OrganizationalUnit = []string{*params.DnOrgUnit} } if *params.DnCountry != "" { subject.Country = []string{*params.DnCountry} } if *params.DnStreet != "" { subject.StreetAddress = []string{*params.DnStreet} } if *params.DnPostal != "" { subject.PostalCode = []string{*params.DnPostal} } logger.Debug("creating certificate struct") cert, err := x509.NewCertificate(nil) if err != nil { return nil, nil, err } cert.Data.Body.Name = *params.Name cert.Data.Body.Expiry = *params.Expiry var ca *x509.CA if *params.CertFile == "" && *params.KeyFile == "" { cert.Data.Body.KeyType = *params.KeyType logger.Debug("generating certificate and key") if *params.Ca == "" { if err := cert.Generate(nil, &subject); err != nil { return nil, nil, err } } else { index, err := cont.env.controllers.org.GetIndex() if err != nil { return nil, nil, err } caId, err := index.GetCA(*params.Ca) if err != nil { return nil, nil, err } ca, err = cont.GetCA(caId) if err != nil { return nil, nil, err } logger.Debugf("generating certificate and signing with CA '%s'", caId) if err := cert.Generate(ca, &subject); err != nil { return nil, nil, err } } } else { if *params.CertFile == "" { return nil, nil, fmt.Errorf("certificate PEM file must be provided if importing") } logger.Debugf("importing certificate from '%s'", *params.CertFile) ok, err := fs.Exists(*params.CertFile) if err != nil { return nil, nil, err } if !ok { logger.Warnf("certificate file '%s' does not exist", *params.CertFile) return nil, nil, nil } logger.Debug("reading certificate from file") certPem, err := fs.ReadFile(*params.CertFile) if err != nil { return nil, nil, err } logger.Debug("decoding certificate PEM") importCert, err := x509.PemDecodeX509Certificate([]byte(certPem)) if err != nil { return nil, nil, err } cert.Data.Body.Id = x509.NewID() cert.Data.Body.Certificate = certPem certExpiry := int(importCert.NotAfter.Sub(importCert.NotBefore) / (time.Hour * 24)) cert.Data.Body.Expiry = certExpiry if *params.KeyFile != "" { logger.Debugf("importing certificate privte key from '%s'", *params.KeyFile) ok, err := fs.Exists(*params.KeyFile) if err != nil { return nil, nil, err } if !ok { logger.Warnf("key file '%s' does not exist", *params.KeyFile) return nil, nil, nil } logger.Debug("reading private key file") keyPem, err := fs.ReadFile(*params.KeyFile) if err != nil { return nil, nil, err } logger.Debug("decoding private key PEM") key, err := crypto.PemDecodePrivate([]byte(keyPem)) if err != nil { return nil, nil, err } logger.Debug("getting key type") keyType, err := crypto.GetKeyType(key) if err != nil { return nil, nil, err } cert.Data.Body.KeyType = string(keyType) cert.Data.Body.PrivateKey = keyPem } } if *params.StandaloneFile == "" { err = cont.SaveCert(cert) if err != nil { return nil, nil, err } var tags string if *params.Tags == "NAME" { tags = *params.Name } else { tags = *params.Tags } err = cont.AddCertToOrgIndex(cert, tags) if err != nil { return nil, nil, err } } logger.Trace("returning certificate") return cert, ca, nil }