Beispiel #1
1
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()
}
Beispiel #2
0
// 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)
}
Beispiel #3
0
// 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
}
Beispiel #4
0
// 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
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}
Beispiel #7
0
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)
	}
}
Beispiel #8
0
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{""}
	}
}
Beispiel #9
0
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
}
Beispiel #10
0
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
}
Beispiel #11
0
// 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
}
Beispiel #12
0
// 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
}
Beispiel #13
0
// 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))
}
Beispiel #14
0
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
}
Beispiel #15
0
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
}
Beispiel #16
0
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
}