// addKeyUsages adds approrpiate key usages to the template given the creation // information func addKeyUsages(creationInfo *creationBundle, certTemplate *x509.Certificate) { certTemplate.KeyUsage = x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement) 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) } if creationInfo.IsCA { // Go performs validation not according to spec but according to the Windows // Crypto API, so we add all usages to CA certs certTemplate.KeyUsage = x509.KeyUsage(certTemplate.KeyUsage | x509.KeyUsageCertSign | x509.KeyUsageCRLSign) certTemplate.ExtKeyUsage = []x509.ExtKeyUsage{ x509.ExtKeyUsageAny, x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageCodeSigning, x509.ExtKeyUsageEmailProtection, x509.ExtKeyUsageTimeStamping, x509.ExtKeyUsageOCSPSigning, } } }
func templateWithCA(template *x509.Certificate) *x509.Certificate { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign template.KeyUsage |= x509.KeyUsageKeyEncipherment template.KeyUsage |= x509.KeyUsageKeyAgreement template.ExtKeyUsage = nil return template }
func createCertificate(commonName string, final bool, parent *x509.Certificate, parentPKey *rsa.PrivateKey) ([]byte, *rsa.PrivateKey) { var keyLength = 2048 var sAlg = SHA256WithRSA pkey, err := rsa.GenerateKey(rand.Reader, keyLength) mustNoErr(err) template := x509.Certificate{ SerialNumber: big.NewInt(time.Now().UnixNano()), IsCA: !final, NotBefore: earlyNotBefore, NotAfter: earlyNotAfter, Subject: pkix.Name{ CommonName: commonName, }, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } if final { if ip := net.ParseIP(commonName); ip != nil { template.IPAddresses = []net.IP{ip} } } template.KeyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature if !final { template.KeyUsage = template.KeyUsage | x509.KeyUsageCertSign } if parent != nil { template.SignatureAlgorithm = parent.SignatureAlgorithm } else { template.SignatureAlgorithm = sAlg } signer := &template publicKey := &pkey.PublicKey privateKey := pkey if parent != nil { if parentPKey == nil { panic("parentPKey should be supplied") } signer = parent privateKey = parentPKey } certDer, err := x509.CreateCertificate(rand.Reader, &template, signer, publicKey, privateKey) mustNoErr(err) return certDer, pkey }
func CreateTLS() *tls.Config { priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { log.Fatal("failed to generate private key:", err) } var notBefore time.Time notBefore = time.Now() notAfter := notBefore.Add(365 * 24 * time.Hour) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.Fatal("failed to generate serial number:", err) } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Wago"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := []string{"127.0.0.1", "::1", "localhost"} for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { log.Fatal("Failed to create certificate:", err) } certPEMBlock := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) keyPEMBlock := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock) if err != nil { log.Fatal(err) } return &tls.Config{ Certificates: []tls.Certificate{cert}, } }
// upgradeCACertificate upgrades a certificate to a self-signing CA certificate if the CN matches. // Issue #108: Allow generated AWS API Gateway certs to be used for client cert authentication func upgradeCACertificate(cert *x509.Certificate, caUpgradeCN string) { if caUpgradeCN != "" && caUpgradeCN == cert.Issuer.CommonName { cert.BasicConstraintsValid = true cert.IsCA = true cert.KeyUsage = x509.KeyUsageCertSign log.Printf("[INFO] cert: Upgrading cert %s to CA cert", cert.Issuer.CommonName) } }
func Certificate(host ...string) (tls.Certificate, error) { priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return tls.Certificate{}, err } notBefore := time.Now() notAfter := notBefore.Add(time.Hour * 24 * 365) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return tls.Certificate{}, err } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } for _, h := range host { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return tls.Certificate{}, err } // create public key certOut := bytes.NewBuffer(nil) pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) // create private key keyOut := bytes.NewBuffer(nil) b, err := x509.MarshalECPrivateKey(priv) if err != nil { return tls.Certificate{}, err } pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) return tls.X509KeyPair(certOut.Bytes(), keyOut.Bytes()) }
// generateRSACerts generates a basic self signed certificate using a key length // of rsaBits, valid for validFor time. func generateRSACerts(host string, isCA bool, keyOut, certOut io.Writer) error { if len(host) == 0 { return fmt.Errorf("Require a non-empty host for client hello") } priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { return fmt.Errorf("Failed to generate key: %v", err) } notBefore := time.Now() notAfter := notBefore.Add(validFor) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return fmt.Errorf("failed to generate serial number: %s", err) } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ CommonName: "default", Organization: []string{"Acme Co"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return fmt.Errorf("Failed to create certificate: %s", err) } if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { return fmt.Errorf("Failed creating cert: %v", err) } if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { return fmt.Errorf("Failed creating keay: %v", err) } return nil }
/* Function to create (missing) cert files */ func CreateCert(host string, cPath *config.CertPaths) error { //Data to work with: const validFor = 365 * 24 * time.Hour const isCA = false const rsaBits = 4096 notBefore := time.Now() notAfter := notBefore.Add(validFor) //Generating a key: priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { return errors.New(fmt.Sprintf("Failed to generate private key: %s\n", err)) } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ Country: []string{"DE"}, Province: []string{"Saxony"}, CommonName: string(host), }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } template.DNSNames = append(template.DNSNames, host) template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return errors.New(fmt.Sprintf("Failed to create certificate: %s", err)) } certOut, err := os.Create(cPath.Certfile) if err != nil { return errors.New(fmt.Sprintf("Failed to open %s for writing: %s", cPath.Certfile, err)) } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() fmt.Printf("Wrote %s\n", cPath.Certfile) keyOut, err := os.OpenFile(cPath.Keyfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return errors.New(fmt.Sprintf("Failed to open %s for writing: %s", cPath.Keyfile, err)) } pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) keyOut.Close() fmt.Printf("Wrote %s\n", cPath.Keyfile) //Finish: return nil }
func createCertificate(d *schema.ResourceData, template, parent *x509.Certificate, pub crypto.PublicKey, priv interface{}) error { var err error template.NotBefore = time.Now() template.NotAfter = template.NotBefore.Add(time.Duration(d.Get("validity_period_hours").(int)) * time.Hour) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) template.SerialNumber, err = rand.Int(rand.Reader, serialNumberLimit) if err != nil { return fmt.Errorf("failed to generate serial number: %s", err) } keyUsesI := d.Get("allowed_uses").([]interface{}) for _, keyUseI := range keyUsesI { keyUse := keyUseI.(string) if usage, ok := keyUsages[keyUse]; ok { template.KeyUsage |= usage } if usage, ok := extKeyUsages[keyUse]; ok { template.ExtKeyUsage = append(template.ExtKeyUsage, usage) } } if d.Get("is_ca_certificate").(bool) { template.IsCA = true template.SubjectKeyId, err = generateSubjectKeyID(pub) if err != nil { return fmt.Errorf("failed to set subject key identifier: %s", err) } } certBytes, err := x509.CreateCertificate(rand.Reader, template, parent, pub, priv) if err != nil { return fmt.Errorf("error creating certificate: %s", err) } certPem := string(pem.EncodeToMemory(&pem.Block{Type: pemCertType, Bytes: certBytes})) validFromBytes, err := template.NotBefore.MarshalText() if err != nil { return fmt.Errorf("error serializing validity_start_time: %s", err) } validToBytes, err := template.NotAfter.MarshalText() if err != nil { return fmt.Errorf("error serializing validity_end_time: %s", err) } d.SetId(template.SerialNumber.String()) d.Set("cert_pem", certPem) d.Set("validity_start_time", string(validFromBytes)) d.Set("validity_end_time", string(validToBytes)) return nil }
// generateTestCert creates a cert and a key used for testing only func generateTestCert(host string) error { certPath := mustGetCertFile() keyPath := mustGetKeyFile() priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return err } serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return err } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Minio Test Cert"}, }, NotBefore: time.Now(), NotAfter: time.Now().Add(time.Minute * 1), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } if ip := net.ParseIP(host); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return err } certOut, err := os.Create(certPath) if err != nil { return err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) keyOut.Close() return nil }
// addKeyUsages adds approrpiate key usages to the template given the creation // information func addKeyUsages(creationInfo *creationBundle, certTemplate *x509.Certificate) { if creationInfo.IsCA { certTemplate.KeyUsage = x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign) return } certTemplate.KeyUsage = creationInfo.KeyUsage if creationInfo.ExtKeyUsage&serverExtKeyUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth) } if creationInfo.ExtKeyUsage&clientExtKeyUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth) } if creationInfo.ExtKeyUsage&codeSigningExtKeyUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning) } if creationInfo.ExtKeyUsage&emailProtectionExtKeyUsage != 0 { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageEmailProtection) } }
func generateSingleCertificate(isCa bool) (*x509.Certificate, error) { var notBefore time.Time var err error if len(validFrom) == 0 { notBefore = time.Now() } else { notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom) if err != nil { return nil, fmt.Errorf("Failed to parse creation date: %s\n", err.Error()) } } notAfter := notBefore.Add(validFor) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return nil, fmt.Errorf("failed to generate serial number: %s\n", err.Error()) } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Arduino LLC US"}, Country: []string{"US"}, CommonName: "localhost", OrganizationalUnit: []string{"IT"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if isCa { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign template.Subject.CommonName = "Arduino" } return &template, nil }
//http://golang.org/src/pkg/crypto/tls/generate_cert.go func generateCertificate(hosts []string) (cert, key []byte) { private, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { log.Fatal(err) } before := time.Now() after := before.Add(10 * 365 * 24 * time.Hour) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.Fatalf("failed to generate serial number: %s", err) } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, NotBefore: before, NotAfter: after, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &private.PublicKey, private) if err != nil { log.Fatalf("Failed to create certificate: %s", err) } certOut := bytes.Buffer{} pem.Encode(&certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) keyOut := bytes.Buffer{} pem.Encode(&keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(private)}) return certOut.Bytes(), keyOut.Bytes() }
func generateCert(hosts []string, notAfter time.Time, isAuthorizedToSign bool) tls.Certificate { priv, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { panic(err) } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, NotBefore: time.Date(1980, time.January, 1, 0, 0, 0, 0, time.UTC), NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } for _, host := range hosts { if ip := net.ParseIP(host); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, host) } } if isAuthorizedToSign { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { panic(err) } certOut := new(bytes.Buffer) pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) keyOut := new(bytes.Buffer) pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) cert, err := tls.X509KeyPair(certOut.Bytes(), keyOut.Bytes()) if err != nil { panic(err) } return cert }
func GenCert(hosts []string, validFor time.Duration, isCA bool) (cert []byte, key []byte, err error) { priv, err := ecdsa.GenerateKey(ellyptic.P521(), rand.Reader) if err != nil { return "", "", err } notBefore := time.Now() notAfter := notBefore.Add(*validFor) if notAfter.After(endOfTime) { notAfter = endOfTime } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(notBefore.UnixNano()), Subject: pkix.Name{ Organization: []string{"Localhost Inc."}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return "", "", err } cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) key := pem.EncodeToMemory(&pem.Block{Type: "ECDSA PRIVATE KEY", Bytes: x509.MarshalECPrivateKey(priv)}) return cert, key, nil }
func MakeCert(organization string, size int, hosts []string, lifespan time.Duration, isCA bool) (*Cert, error) { var err error var cert Cert if cert.privateKey, err = rsa.GenerateKey(rand.Reader, size); err != nil { return nil, errors.New(fmt.Sprintf("Unable to generate key [%s]\n", err)) } // Setup certificate expiration notBefore := time.Now() notAfter := notBefore.Add(lifespan) // Setup certificate configuration template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ Organization: []string{organization}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } // Separate valid IP addresses from the named hosts provided for _, host := range hosts { if ip := net.ParseIP(host); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, host) } } // Append usage for Cert Signing if CA is specified if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } // Make certificate blob if cert.data, err = x509.CreateCertificate(rand.Reader, &template, &template, &cert.privateKey.PublicKey, cert.privateKey); err != nil { return nil, errors.New(fmt.Sprintf("Unable to create certificate [%s]\n", err)) } return &cert, nil }
// GenClientCert generates a client certificate. // The generated certificate will have its extended key usage set to 'client authentication' and will be ready for use in TLS client authentication. // The returned slices are the PEM encoded X.509 certificate and private key pair. func GenClientCert(subject pkix.Name, validFor time.Duration, keyLength int, signingCert, signingKey []byte) (cert, key []byte, err error) { var ( sc, c *x509.Certificate sk, k *rsa.PrivateKey ) if sc, sk, err = parseCertAndKey(signingCert, signingKey); err != nil { return } if c, k, err = createBaseCert(subject, validFor, keyLength); err != nil { return } c.KeyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature c.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} c.IsCA = false cert, key, err = signAndEncodeCert(sc, sk, c, k) return }
func finalizeTLSConfig(tlsConfig *tls.Config, tlsRemoteCert *x509.Certificate) { // Trusted certificates if tlsRemoteCert != nil { caCertPool := x509.NewCertPool() // Make it a valid RootCA tlsRemoteCert.IsCA = true tlsRemoteCert.KeyUsage = x509.KeyUsageCertSign // Setup the pool caCertPool.AddCert(tlsRemoteCert) tlsConfig.RootCAs = caCertPool // Set the ServerName if tlsRemoteCert.DNSNames != nil { tlsConfig.ServerName = tlsRemoteCert.DNSNames[0] } } tlsConfig.BuildNameToCertificate() }
// GenCACert generates a CA certificate. // If signingCert and signingKey are not provided, the certificate is created as a self-signed root CA. // If signingCert and signingKey are provided, the certificate is created as an intermediate CA, signed with provided certificate. // The generated certificate can only be used for signing other certificates and CRLs. // The returned slices are the PEM encoded X.509 certificate and private key pair. func GenCACert(subject pkix.Name, validFor time.Duration, keyLength int, signingCert, signingKey []byte) (cert, key []byte, err error) { var ( sc, c *x509.Certificate sk, k *rsa.PrivateKey ) if c, k, err = createBaseCert(subject, validFor, keyLength); err != nil { return } if signingCert == nil || signingKey == nil { sc = c sk = k } else if sc, sk, err = parseCertAndKey(signingCert, signingKey); err != nil { return } c.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageCRLSign c.IsCA = true cert, key, err = signAndEncodeCert(sc, sk, c, k) return }
// FillTemplate is a utility function that tries to load as much of // the certificate template as possible from the profiles and current // template. It fills in the key uses, expiration, revocation URLs // and SKI. func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.SigningProfile) error { ski, err := ComputeSKI(template) var ( eku []x509.ExtKeyUsage ku x509.KeyUsage backdate time.Duration expiry time.Duration notBefore time.Time notAfter time.Time crlURL, ocspURL string ) // The third value returned from Usages is a list of unknown key usages. // This should be used when validating the profile at load, and isn't used // here. ku, eku, _ = profile.Usages() if profile.IssuerURL == nil { profile.IssuerURL = defaultProfile.IssuerURL } if ku == 0 && len(eku) == 0 { return cferr.New(cferr.PolicyError, cferr.NoKeyUsages) } if expiry = profile.Expiry; expiry == 0 { expiry = defaultProfile.Expiry } if crlURL = profile.CRL; crlURL == "" { crlURL = defaultProfile.CRL } if ocspURL = profile.OCSP; ocspURL == "" { ocspURL = defaultProfile.OCSP } if backdate = profile.Backdate; backdate == 0 { backdate = -5 * time.Minute } else { backdate = -1 * profile.Backdate } if !profile.NotBefore.IsZero() { notBefore = profile.NotBefore.UTC() } else { notBefore = time.Now().Round(time.Minute).Add(backdate).UTC() } if !profile.NotAfter.IsZero() { notAfter = profile.NotAfter.UTC() } else { notAfter = notBefore.Add(expiry).UTC() } template.NotBefore = notBefore template.NotAfter = notAfter template.KeyUsage = ku template.ExtKeyUsage = eku template.BasicConstraintsValid = true template.IsCA = profile.CA template.SubjectKeyId = ski if ocspURL != "" { template.OCSPServer = []string{ocspURL} } if crlURL != "" { template.CRLDistributionPoints = []string{crlURL} } if len(profile.IssuerURL) != 0 { template.IssuingCertificateURL = profile.IssuerURL } if len(profile.Policies) != 0 { err = addPolicies(template, profile.Policies) if err != nil { return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err) } } if profile.OCSPNoCheck { ocspNoCheckExtension := pkix.Extension{ Id: asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5}, Critical: false, Value: []byte{0x05, 0x00}, } template.ExtraExtensions = append(template.ExtraExtensions, ocspNoCheckExtension) } return nil }
func (s *Signer) sign(template *x509.Certificate, profile *config.SigningProfile) (cert []byte, err error) { pub := template.PublicKey encodedpub, err := x509.MarshalPKIXPublicKey(pub) if err != nil { return } pubhash := sha1.New() pubhash.Write(encodedpub) if profile == nil { profile = s.Policy.Default } var ( eku []x509.ExtKeyUsage ku x509.KeyUsage expiry time.Duration crlURL, ocspURL string ) // The third value returned from Usages is a list of unknown key usages. // This should be used when validating the profile at load, and isn't used // here. ku, eku, _ = profile.Usages() expiry = profile.Expiry if profile.IssuerURL == nil { profile.IssuerURL = s.Policy.Default.IssuerURL } if ku == 0 && len(eku) == 0 { err = cferr.New(cferr.PolicyError, cferr.NoKeyUsages, errors.New("no key usage available")) return } if expiry == 0 { expiry = s.Policy.Default.Expiry } if crlURL = profile.CRL; crlURL == "" { crlURL = s.Policy.Default.CRL } if ocspURL = profile.OCSP; ocspURL == "" { ocspURL = s.Policy.Default.OCSP } now := time.Now() serialNumber, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) if err != nil { err = cferr.New(cferr.CertificateError, cferr.Unknown, err) } template.SerialNumber = serialNumber template.NotBefore = now.Add(-5 * time.Minute).UTC() template.NotAfter = now.Add(expiry).UTC() template.KeyUsage = ku template.ExtKeyUsage = eku template.BasicConstraintsValid = true template.IsCA = profile.CA template.SubjectKeyId = pubhash.Sum(nil) if ocspURL != "" { template.OCSPServer = []string{ocspURL} } if crlURL != "" { template.CRLDistributionPoints = []string{crlURL} } if len(profile.IssuerURL) != 0 { template.IssuingCertificateURL = profile.IssuerURL } var initRoot bool if s.CA == nil { if !template.IsCA { err = cferr.New(cferr.PolicyError, cferr.InvalidRequest, nil) return } template.DNSNames = nil s.CA = template initRoot = true template.MaxPathLen = 2 } else if template.IsCA { template.MaxPathLen = 1 template.DNSNames = nil } derBytes, err := x509.CreateCertificate(rand.Reader, template, s.CA, pub, s.Priv) if err != nil { return } if initRoot { s.CA, err = x509.ParseCertificate(derBytes) if err != nil { err = cferr.New(cferr.CertificateError, cferr.ParseFailed, err) return } } cert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) return }
func Generate(certPath string, keyPath string, host string) error { var priv interface{} var err error switch ecdsaCurve { case "": priv, err = rsa.GenerateKey(rand.Reader, rsaBits) case "P224": priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) case "P256": priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) case "P384": priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) case "P521": priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) default: fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", ecdsaCurve) os.Exit(1) } if err != nil { log.Printf("failed to generate private key: %s", err) return err } var notBefore time.Time if len(validFrom) == 0 { notBefore = time.Now() } else { notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom) if err != nil { fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err) return err } } notAfter := notBefore.Add(validFor) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.Printf("failed to generate serial number: %s", err) return err } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) if err != nil { log.Printf("Failed to create certificate: %s", err) return err } certOut, err := os.Create(certPath) if err != nil { log.Printf("failed to open "+certPath+" for writing: %s", err) return err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() log.Print("written cert.pem\n") keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Print("failed to open "+keyPath+" for writing:", err) return err } pem.Encode(keyOut, pemBlockForKey(priv)) keyOut.Close() log.Print("written key.pem\n") return nil }
func GenerateFakeX509Certificate(certType string) (string, string) { priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { logging.GetLogger().Fatal("ECDSA GenerateKey failed : " + err.Error()) } serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { logging.GetLogger().Fatal("Serial number generation error : " + err.Error()) } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Skydive Co"}, }, NotBefore: time.Now(), NotAfter: time.Now().Add(1 * time.Hour), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, BasicConstraintsValid: true, } if certType == "server" { template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} } else { template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} } hosts := strings.Split("127.0.0.1,::1", ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } template.DNSNames = append(template.DNSNames, "localhost") template.EmailAddresses = append(template.EmailAddresses, "*****@*****.**") /* Generate CA */ template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign /* Certificate */ derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) if err != nil { logging.GetLogger().Fatalf("Failed to create certificate: %s", err) } basedir, err := ioutil.TempDir("", "skydive-keys") if err != nil { logging.GetLogger().Fatal("can't create tempdir skydive-keys") } certFilename := filepath.Join(basedir, "cert.pem") certOut, err := os.Create(certFilename) if err != nil { logging.GetLogger().Fatalf("failed to open %s for writing: %s", certFilename, err) } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() /* Private Key */ privKeyFilename := filepath.Join(basedir, "key.pem") keyOut, err := os.OpenFile(privKeyFilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { logging.GetLogger().Fatalf("failed to open %s for writing: %s", privKeyFilename, err) } pem.Encode(keyOut, pemBlockForKey(priv)) keyOut.Close() return certFilename, privKeyFilename }
func generateCertificates(host string) { var priv interface{} var err error priv, err = rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { log.Fatalf("failed to generate private key: %s", err) } var notBefore = validFrom notAfter := notBefore.Add(validFor) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.Fatalf("failed to generate serial number: %s", err) } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) if err != nil { log.Fatalf("Failed to create certificate: %s", err) } certOut, err := os.Create("cert.pem") if err != nil { log.Fatalf("failed to open cert.pem for writing: %s", err) } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() log.Print("written cert.pem\n") keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Print("failed to open key.pem for writing:", err) return } pem.Encode(keyOut, pemBlockForKey(priv)) keyOut.Close() log.Print("written key.pem\n") }
func createCertAndKey(certPath, keyPath, host string, ca bool) error { validFrom := "" validFor := 365 * 24 * time.Hour rsaBits := 1024 priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { return err } var notBefore time.Time if len(validFrom) == 0 { notBefore = time.Now() } else { notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom) if err != nil { return err } } notAfter := notBefore.Add(validFor) // end of ASN.1 time endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) if notAfter.After(endOfTime) { notAfter = endOfTime } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if ca { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return err } certOut, err := os.Create("cert.pem") if err != nil { return err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) keyOut.Close() return nil }
func generateCert(logger *gosteno.Logger) { // see: http://golang.org/src/pkg/crypto/tls/generate_cert.go host := "localhost" validFrom := "Jan 1 15:04:05 2011" validFor := 10 * 365 * 24 * time.Hour isCA := true rsaBits := 1024 if len(host) == 0 { logger.Fatalf("Missing required --host parameter") } priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { logger.Fatalf("failed to generate private key: %s", err) panic(err) } var notBefore time.Time if len(validFrom) == 0 { notBefore = time.Now() } else { notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom) if err != nil { logger.Fatalf("Failed to parse creation date: %s\n", err) panic(err) } } notAfter := notBefore.Add(validFor) // end of ASN.1 time endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) if notAfter.After(endOfTime) { notAfter = endOfTime } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ Organization: []string{"Loggregator TrafficController TEST"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { logger.Fatalf("Failed to create certificate: %s", err) panic(err) } certOut, err := os.Create("cert.pem") if err != nil { logger.Fatalf("failed to open cert.pem for writing: %s", err) panic(err) } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() logger.Info("written cert.pem\n") keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { logger.Fatalf("failed to open key.pem for writing: %s", err) panic(err) } pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) keyOut.Close() logger.Info("written key.pem\n") }
func GenerateCertifcate(pkiroot, name string, template *x509.Certificate) error { // TODO(jclerc): check that pki has been init var crtPath string privateKeyPath := filepath.Join(pkiroot, "private", name+".key") if name == "ca" { crtPath = filepath.Join(pkiroot, name+".crt") } else { crtPath = filepath.Join(pkiroot, "issued", name+".crt") } var caCrt *x509.Certificate var caKey *rsa.PrivateKey if _, err := os.Stat(privateKeyPath); err == nil { return fmt.Errorf("a key pair for %v already exists", name) } privateKey, err := GeneratePrivateKey(privateKeyPath) if err != nil { return fmt.Errorf("generate private key: %v", err) } publicKeyBytes, err := asn1.Marshal(*privateKey.Public().(*rsa.PublicKey)) if err != nil { return fmt.Errorf("marshal public key: %v", err) } subjectKeyId := sha1.Sum(publicKeyBytes) template.SubjectKeyId = subjectKeyId[:] template.NotBefore = time.Now() template.SignatureAlgorithm = x509.SHA256WithRSA if template.IsCA { serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return fmt.Errorf("failed to generate ca serial number: %s", err) } template.SerialNumber = serialNumber template.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageCRLSign template.BasicConstraintsValid = true template.Issuer = template.Subject template.AuthorityKeyId = template.SubjectKeyId caCrt = template caKey = privateKey } else { template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment serialNumber, err := NextNumber(pkiroot, "serial") if err != nil { return fmt.Errorf("get next serial: %v", err) } template.SerialNumber = serialNumber caCrt, caKey, err = GetCA(pkiroot) if err != nil { return fmt.Errorf("get ca: %v", err) } } crt, err := x509.CreateCertificate(rand.Reader, template, caCrt, privateKey.Public(), caKey) if err != nil { return fmt.Errorf("create certificate: %v", err) } crtFile, err := os.Create(crtPath) if err != nil { return fmt.Errorf("create %v: %v", crtPath, err) } defer crtFile.Close() err = pem.Encode(crtFile, &pem.Block{ Type: "CERTIFICATE", Bytes: crt, }) if err != nil { return fmt.Errorf("pem encode crt: %v", err) } // I do not think we have to write the ca.crt in the index if !template.IsCA { WriteIndex(pkiroot, name, template) if err != nil { return fmt.Errorf("write index: %v", err) } } return nil }
// Generate a self-signed X.509 certificate for a TLS server. Outputs to // certFile and keyFile and will overwrite existing files. func GenerateCert(certFile, keyFile, host, organization string, rsaBits int, isCA bool, validFrom time.Time, validFor time.Duration) error { priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { return fmt.Errorf("Failed to generate private key: %v", err) } notBefore := validFrom notAfter := notBefore.Add(validFor) // end of ASN.1 time endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) if notAfter.After(endOfTime) { notAfter = endOfTime } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ Organization: []string{organization}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return fmt.Errorf("Failed to create certificate: %v", err) } certOut, err := os.Create(certFile) if err != nil { return fmt.Errorf("Failed to open %s for writing: %v", certFile, err) } defer certOut.Close() pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return fmt.Errorf("Failed to open %s for writing:", keyFile, err) } defer keyOut.Close() pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) return nil }
// GenerateCA func GenerateCert(validFrom time.Time, validFor time.Duration, isCA bool, rsaBits int, subject pkix.Name, certName string) error { /* if host == "" { log.Fatalf("Missing required host parameter.") } */ if rsaBits == 0 { rsaBits = 2048 } priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { log.Printf("faild to generate private key: %s", err) return err } var notBefore time.Time if validFrom.IsZero() { notBefore = time.Now() } else { notBefore = validFrom } notAfter := notBefore.Add(validFor) serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { log.Printf("failed to generate serial number: %s", err) return err } template := x509.Certificate{ SerialNumber: serialNumber, Subject: subject, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{ x509.ExtKeyUsageServerAuth, }, BasicConstraintsValid: true, } /* hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } */ var parent *x509.Certificate if isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign parent = &template } derBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &priv.PublicKey, priv) if err != nil { log.Printf("Failed to create certificate: %s", err) return err } certOut, err := os.Create(fmt.Sprintf("%s.crt", certName)) if err != nil { log.Printf("failed to open %s.crt for writing: %s", certName, err) return err } defer certOut.Close() pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) log.Printf("written %s.crt\n", certName) keyOut, err := os.OpenFile(fmt.Sprintf("%s.key", certName), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Printf("failed to open %s.key for writing:", err) return err } defer keyOut.Close() pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) log.Printf("written %s.key\n", certName) return nil }
func main() { flag.Parse() if len(*host) == 0 { log.Fatalf("Missing required --host parameter") } priv, err := rsa.GenerateKey(rand.Reader, *rsaBits) if err != nil { log.Fatalf("failed to generate private key: %s", err) return } var notBefore time.Time if len(*validFrom) == 0 { notBefore = time.Now() } else { notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom) if err != nil { fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err) os.Exit(1) } } notAfter := notBefore.Add(*validFor) // end of ASN.1 time endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) if notAfter.After(endOfTime) { notAfter = endOfTime } template := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } hosts := strings.Split(*host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } if *isCA { template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { log.Fatalf("Failed to create certificate: %s", err) return } certOut, err := os.Create("cert.pem") if err != nil { log.Fatalf("failed to open cert.pem for writing: %s", err) return } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() log.Print("written cert.pem\n") keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Print("failed to open key.pem for writing:", err) return } pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) keyOut.Close() log.Print("written key.pem\n") }