// Creates a CSR. This is currently only meant for use when // generating an intermediate certificate. func createCSR(creationInfo *creationBundle) (*certutil.ParsedCSRBundle, error) { var err error result := &certutil.ParsedCSRBundle{} if err := certutil.GeneratePrivateKey(creationInfo.KeyType, creationInfo.KeyBits, result); err != nil { return nil, err } // Like many root CAs, other information is ignored subject := pkix.Name{ CommonName: creationInfo.CommonName, } csrTemplate := &x509.CertificateRequest{ Subject: subject, DNSNames: creationInfo.DNSNames, EmailAddresses: creationInfo.EmailAddresses, IPAddresses: creationInfo.IPAddresses, } switch creationInfo.KeyType { case "rsa": csrTemplate.SignatureAlgorithm = x509.SHA256WithRSA case "ec": csrTemplate.SignatureAlgorithm = x509.ECDSAWithSHA256 } csr, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, result.PrivateKey) if err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("unable to create certificate: %s", err)} } result.CSRBytes = csr result.CSR, err = x509.ParseCertificateRequest(csr) if err != nil { return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)} } 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, 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 *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 }