// Performs the heavy lifting of creating a certificate. Returns // a fully-filled-in ParsedCertBundle. func createCertificate(creationInfo *creationBundle) (*certutil.ParsedCertBundle, error) { var err error result := &certutil.ParsedCertBundle{} serialNumber, err := certutil.GenerateSerialNumber() if err != nil { return nil, err } if err := certutil.GeneratePrivateKey(creationInfo.KeyType, creationInfo.KeyBits, result); err != nil { return nil, err } subjKeyID, err := certutil.GetSubjKeyID(result.PrivateKey) if err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("error getting subject key ID: %s", err)} } subject := pkix.Name{ CommonName: creationInfo.CommonName, } certTemplate := &x509.Certificate{ SerialNumber: serialNumber, Subject: subject, NotBefore: time.Now().Add(-30 * time.Second), NotAfter: time.Now().Add(creationInfo.TTL), IsCA: false, SubjectKeyId: subjKeyID, DNSNames: creationInfo.DNSNames, EmailAddresses: creationInfo.EmailAddresses, IPAddresses: creationInfo.IPAddresses, } // Add this before calling addKeyUsages if creationInfo.SigningBundle == nil { certTemplate.IsCA = true } addKeyUsages(creationInfo, certTemplate) certTemplate.IssuingCertificateURL = creationInfo.URLs.IssuingCertificates certTemplate.CRLDistributionPoints = creationInfo.URLs.CRLDistributionPoints certTemplate.OCSPServer = creationInfo.URLs.OCSPServers var certBytes []byte if creationInfo.SigningBundle != nil { switch creationInfo.SigningBundle.PrivateKeyType { case certutil.RSAPrivateKey: certTemplate.SignatureAlgorithm = x509.SHA256WithRSA case certutil.ECPrivateKey: certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 } caCert := creationInfo.SigningBundle.Certificate certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, result.PrivateKey.Public(), creationInfo.SigningBundle.PrivateKey) } else { // Creating a self-signed root if creationInfo.MaxPathLength == 0 { certTemplate.MaxPathLen = 0 certTemplate.MaxPathLenZero = true } else { certTemplate.MaxPathLen = creationInfo.MaxPathLength } switch creationInfo.KeyType { case "rsa": certTemplate.SignatureAlgorithm = x509.SHA256WithRSA case "ec": certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 } certTemplate.BasicConstraintsValid = true certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey) } if err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)} } result.CertificateBytes = certBytes result.Certificate, err = x509.ParseCertificate(certBytes) if err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)} } if creationInfo.SigningBundle != nil { result.IssuingCABytes = creationInfo.SigningBundle.CertificateBytes result.IssuingCA = creationInfo.SigningBundle.Certificate } else { result.IssuingCABytes = result.CertificateBytes result.IssuingCA = result.Certificate } return result, nil }
// Performs the heavy lifting of creating a certificate. Returns // a fully-filled-in ParsedCertBundle. func createCertificate(creationInfo *certCreationBundle) (*certutil.ParsedCertBundle, error) { var clientPrivKey crypto.Signer var err error result := &certutil.ParsedCertBundle{} var serialNumber *big.Int serialNumber, err = rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil)) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("Error getting random serial number")} } switch creationInfo.KeyType { case "rsa": result.PrivateKeyType = certutil.RSAPrivateKey clientPrivKey, err = rsa.GenerateKey(rand.Reader, creationInfo.KeyBits) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("Error generating RSA private key")} } result.PrivateKey = clientPrivKey result.PrivateKeyBytes = x509.MarshalPKCS1PrivateKey(clientPrivKey.(*rsa.PrivateKey)) case "ec": result.PrivateKeyType = certutil.ECPrivateKey var curve elliptic.Curve switch creationInfo.KeyBits { case 224: curve = elliptic.P224() case 256: curve = elliptic.P256() case 384: curve = elliptic.P384() case 521: curve = elliptic.P521() default: return nil, certutil.UserError{Err: fmt.Sprintf("Unsupported bit length for EC key: %d", creationInfo.KeyBits)} } clientPrivKey, err = ecdsa.GenerateKey(curve, rand.Reader) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("Error generating EC private key")} } result.PrivateKey = clientPrivKey result.PrivateKeyBytes, err = x509.MarshalECPrivateKey(clientPrivKey.(*ecdsa.PrivateKey)) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("Error marshalling EC private key")} } default: return nil, certutil.UserError{Err: fmt.Sprintf("Unknown key type: %s", creationInfo.KeyType)} } subjKeyID, err := certutil.GetSubjKeyID(result.PrivateKey) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("Error getting subject key ID: %s", err)} } subject := pkix.Name{ Country: creationInfo.CACert.Subject.Country, Organization: creationInfo.CACert.Subject.Organization, OrganizationalUnit: creationInfo.CACert.Subject.OrganizationalUnit, Locality: creationInfo.CACert.Subject.Locality, Province: creationInfo.CACert.Subject.Province, StreetAddress: creationInfo.CACert.Subject.StreetAddress, PostalCode: creationInfo.CACert.Subject.PostalCode, SerialNumber: serialNumber.String(), CommonName: creationInfo.CommonNames[0], } certTemplate := &x509.Certificate{ SignatureAlgorithm: x509.SHA256WithRSA, SerialNumber: serialNumber, Subject: subject, NotBefore: time.Now(), NotAfter: time.Now().Add(creationInfo.Lease), KeyUsage: x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement), BasicConstraintsValid: true, IsCA: false, SubjectKeyId: subjKeyID, DNSNames: creationInfo.CommonNames, IPAddresses: creationInfo.IPSANs, PermittedDNSDomainsCritical: false, PermittedDNSDomains: nil, CRLDistributionPoints: creationInfo.CACert.CRLDistributionPoints, } if creationInfo.Usage&serverUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth) } if creationInfo.Usage&clientUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth) } if creationInfo.Usage&codeSigningUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning) } cert, err := x509.CreateCertificate(rand.Reader, certTemplate, creationInfo.CACert, clientPrivKey.Public(), creationInfo.SigningBundle.PrivateKey) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("Unable to create certificate: %s", err)} } result.CertificateBytes = cert result.Certificate, err = x509.ParseCertificate(cert) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("Unable to parse created certificate: %s", err)} } result.IssuingCABytes = creationInfo.SigningBundle.CertificateBytes result.IssuingCA = creationInfo.SigningBundle.Certificate return result, nil }
// Performs the heavy lifting of creating a certificate. Returns // a fully-filled-in ParsedCertBundle. func createCertificate(creationInfo *creationBundle) (*certutil.ParsedCertBundle, error) { var err error result := &certutil.ParsedCertBundle{} serialNumber, err := certutil.GenerateSerialNumber() if err != nil { return nil, err } if err := certutil.GeneratePrivateKey(creationInfo.KeyType, creationInfo.KeyBits, result); err != nil { return nil, err } subjKeyID, err := certutil.GetSubjKeyID(result.PrivateKey) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("error getting subject key ID: %s", err)} } subject := pkix.Name{ CommonName: creationInfo.CommonName, } certTemplate := &x509.Certificate{ SerialNumber: serialNumber, Subject: subject, NotBefore: time.Now(), NotAfter: time.Now().Add(creationInfo.TTL), KeyUsage: x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement), IsCA: false, SubjectKeyId: subjKeyID, DNSNames: creationInfo.DNSNames, EmailAddresses: creationInfo.EmailAddresses, IPAddresses: creationInfo.IPAddresses, } if creationInfo.Usage&serverUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth) } if creationInfo.Usage&clientUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth) } if creationInfo.Usage&codeSigningUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning) } if creationInfo.Usage&emailProtectionUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageEmailProtection) } certTemplate.IssuingCertificateURL = creationInfo.URLs.IssuingCertificates certTemplate.CRLDistributionPoints = creationInfo.URLs.CRLDistributionPoints certTemplate.OCSPServer = creationInfo.URLs.OCSPServers var certBytes []byte if creationInfo.SigningBundle != nil { switch creationInfo.SigningBundle.PrivateKeyType { case certutil.RSAPrivateKey: certTemplate.SignatureAlgorithm = x509.SHA256WithRSA case certutil.ECPrivateKey: certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 } caCert := creationInfo.SigningBundle.Certificate certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, caCert, result.PrivateKey.Public(), creationInfo.SigningBundle.PrivateKey) } else { // Creating a self-signed root if creationInfo.MaxPathLength == 0 { certTemplate.MaxPathLen = 0 certTemplate.MaxPathLenZero = true } else { certTemplate.MaxPathLen = creationInfo.MaxPathLength } switch creationInfo.KeyType { case "rsa": certTemplate.SignatureAlgorithm = x509.SHA256WithRSA case "ec": certTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 } certTemplate.BasicConstraintsValid = true certTemplate.IsCA = true certTemplate.KeyUsage = x509.KeyUsage(certTemplate.KeyUsage | x509.KeyUsageCertSign | x509.KeyUsageCRLSign) certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageOCSPSigning) certBytes, err = x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, result.PrivateKey.Public(), result.PrivateKey) } if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)} } result.CertificateBytes = certBytes result.Certificate, err = x509.ParseCertificate(certBytes) if err != nil { return nil, certutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)} } if creationInfo.SigningBundle != nil { result.IssuingCABytes = creationInfo.SigningBundle.CertificateBytes result.IssuingCA = creationInfo.SigningBundle.Certificate } else { result.IssuingCABytes = result.CertificateBytes result.IssuingCA = result.Certificate } return result, nil }