func TestTLSConnection(t *testing.T) { reactor := NewReactor() client := reactor.CreateServer("local") initialiseServerConnection(client) // generate a test certificate to use priv, _ := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) duration30Days, _ := time.ParseDuration("-30h") notBefore := time.Now().Add(duration30Days) // valid 30 hours ago duration1Year, _ := time.ParseDuration("90h") notAfter := notBefore.Add(duration1Year) // for 90 hours serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit) template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"gIRC-Go Co"}, }, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, IsCA: true, } template.IPAddresses = append(template.IPAddresses, net.ParseIP("127.0.0.1")) template.IPAddresses = append(template.IPAddresses, net.ParseIP("::")) template.DNSNames = append(template.DNSNames, "localhost") derBytes, _ := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) c := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) b, _ := x509.MarshalECPrivateKey(priv) k := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) // we mock up a server connection to test the client listenerKeyPair, _ := tls.X509KeyPair(c, k) var listenerTLSConfig tls.Config listenerTLSConfig.Certificates = make([]tls.Certificate, 0) listenerTLSConfig.Certificates = append(listenerTLSConfig.Certificates, listenerKeyPair) listener, _ := tls.Listen("tcp", ":0", &listenerTLSConfig) // mock up the client side too clientTLSCertPool := x509.NewCertPool() clientTLSCertPool.AppendCertsFromPEM(c) var clientTLSConfig tls.Config clientTLSConfig.RootCAs = clientTLSCertPool clientTLSConfig.ServerName = "localhost" go client.Connect(listener.Addr().String(), true, &clientTLSConfig) go client.ReceiveLoop() testServerConnection(t, reactor, client, listener) }
// ValidateEccentricCertificate verifies that the given certificate parses to a real x509 certificate // and that it is signed by the FPCA // DANE/TLSA record it specifies in the CN. // TODO: Deprecate this function as it handles only direct signing by the FPCA, no SubCAs // Use ValidateEccentricCertificateChain instead func ValidateEccentricCertificate(cl_cert *x509.Certificate) (caCert *x509.Certificate, err error) { log.Printf("Validate Eccentric Certificate got client certificate: Issuer: %#v\nand Subject: %#v", cl_cert.Issuer, cl_cert.Subject) // Check the cn if it has the @@ in it. cn := cl_cert.Subject.CommonName // the chosen userid@@realm log.Printf("Subject CommonName is %v\n", cn) _, _, err = ParseCN(cn) if err != nil { return nil, err } // Now fetch the issuer. That must be the FPCA. issuer := cl_cert.Issuer.CommonName if issuer == "" { return nil, errors.New("Certificate does not look like an Eccentric Authenticated client certificate. It has an empty Issuer.CommonName. We expect the fqdn of its FPCA.") } unb := unbound.New() caCert, err = unb.GetCACert(issuer) check(err) log.Printf("Got certificate: Issuer: %#v\nand Subject: %#v", caCert.Issuer, caCert.Subject) err = cl_cert.CheckSignatureFrom(caCert) check(err) // TODO: give out neat error at validation failure, not a panic. return caCert, nil }
func NewS3Session(auth *aws.Auth, region aws.Region) *s3.S3 { var s3Session *s3.S3 cert := x509.Certificate{} // go's systemVerify panics with no verify options set // TODO: EVG-483 if runtime.GOOS == "windows" { s3Session = s3.New(*auth, region) s3Session.ReadTimeout = S3ReadTimeout s3Session.WriteTimeout = S3WriteTimeout s3Session.ConnectTimeout = S3ConnectTimeout return s3Session } // no verify options so system root ca will be used _, err := cert.Verify(x509.VerifyOptions{}) rootsError := x509.SystemRootsError{} if err != nil && err.Error() == rootsError.Error() { // create a Transport which includes our TLSConfig with InsecureSkipVerify // and client timeouts. tlsConfig := tls.Config{InsecureSkipVerify: true} tr := http.Transport{ TLSClientConfig: &tlsConfig} // add the Transport to our http client client := &http.Client{Transport: &tr} s3Session = s3.New(*auth, region, client) } else { s3Session = s3.New(*auth, region) } s3Session.ReadTimeout = S3ReadTimeout s3Session.WriteTimeout = S3WriteTimeout s3Session.ConnectTimeout = S3ConnectTimeout return s3Session }
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}, } }
// GenerateSelfSignedCert creates a self-signed certificate and key for the given host. // Host may be an IP or a DNS name // The certificate will be created with file mode 0644. The key will be created with file mode 0600. // If the certificate or key files already exist, they will be overwritten. // Any parent directories of the certPath or keyPath will be created as needed with file mode 0755. func GenerateSelfSignedCert(host, certPath, keyPath string) error { priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return err } template := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()), }, NotBefore: time.Now(), NotAfter: time.Now().Add(time.Hour * 24 * 365), 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) } else { template.DNSNames = append(template.DNSNames, host) } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return err } // Generate cert certBuffer := bytes.Buffer{} if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { return err } // Generate key keyBuffer := bytes.Buffer{} if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { return err } // Write cert if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil { return err } if err := ioutil.WriteFile(certPath, certBuffer.Bytes(), os.FileMode(0644)); err != nil { return err } // Write key if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil { return err } if err := ioutil.WriteFile(keyPath, keyBuffer.Bytes(), os.FileMode(0600)); err != nil { return err } return nil }
// Sign signs a new certificate based on the PEM-encoded client // certificate or certificate request with the signing profile, specified by profileName. // The certificate will be valid for the host named in the hostName parameter. func (s *Signer) Sign(hostName string, in []byte, profileName string) (cert []byte, err error) { profile := s.Policy.Profiles[profileName] block, _ := pem.Decode(in) if block == nil { return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed, err) } var template *x509.Certificate switch block.Type { case "CERTIFICATE": template, err = helpers.ParseSelfSignedCertificatePEM(in) case "CERTIFICATE REQUEST": template, err = s.parseCertificateRequest(block.Bytes) default: return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed, errors.New("Not a certificate or csr.")) } if err != nil { return } if ip := net.ParseIP(hostName); ip != nil { template.IPAddresses = []net.IP{ip} } else { template.DNSNames = []string{hostName} } return s.sign(template, profile) }
func fetchCertificateChain(cl_cert *x509.Certificate, root *x509.Certificate) (chain []x509.Certificate, err error) { // check if cl_cert is signed by Root if cl_cert.Issuer.CommonName == root.Subject.CommonName { // client cert is signed by Root, there are no (more) intermediaries. We're done. chain = append(chain, *root) return chain, nil } issuer := cl_cert.Issuer.CommonName if issuer == "" { // chain is empty at this point. return chain, errors.New("Certificate does not look like an Eccentric Authenticated Intermediate certificate. It has an empty Issuer.CommonName. We expect the fqdn of its FPCA.") } unb := unbound.New() caCert, err := unb.GetCACert(issuer) check(err) log.Printf("Got certificate: Issuer: %#v\nand Subject: %#v", caCert.Issuer, caCert.Subject) // check if the signature matches err = cl_cert.CheckSignatureFrom(caCert) check(err) // TODO: give out neat error at validation failure, not a panic. // recurse to get higher up the tree. chain, err = FetchCertificateChain(caCert, root) if err != nil { return } // empty, err chain = append(chain, *caCert) return // chain, nil }
func (crtkit *CertKit) GenerateServer(subject pkix.Name, host, email string, NotBefore ...time.Time) error { var e error var derBytes []byte var notBefore time.Time priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return errors.New(fmt.Sprintf("failed to generate private key: %s", err)) } if len(NotBefore) > 0 { notBefore = NotBefore[0] } else { notBefore = time.Now() } serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) if err != nil { return errors.New(fmt.Sprintf("failed to generate serial number: %s", err)) } if host == "" { host, _ = os.Hostname() } Goose.Generator.Logf(6, "Certificate authority used: %#v", crtkit.CACert) template := x509.Certificate{ SerialNumber: serialNumber, Subject: subject, IsCA: false, NotBefore: notBefore, NotAfter: notBefore.Add(365 * 24 * time.Hour), DNSNames: []string{host, strings.Split(host, ".")[0]}, AuthorityKeyId: crtkit.CACert.SubjectKeyId, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageContentCommitment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, } Goose.Generator.Logf(4, "X509 Template: %#v", template) if crtkit.CACert.CRLDistributionPoints != nil { template.CRLDistributionPoints = crtkit.CACert.CRLDistributionPoints } else { Goose.Generator.Logf(1, "Certificate authority without CRL distribution points") } crtkit.ServerKey = priv crtkit.ServerCert = &template derBytes, e = x509.CreateCertificate(rand.Reader, &template, crtkit.CACert, &priv.PublicKey, crtkit.CAKey) if e != nil { return errors.New(fmt.Sprintf("Failed to create certificate: %s", e)) } Goose.Generator.Logf(4, "DER Certificate: %s", derBytes) crtkit.ServerCertPem = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) crtkit.ServerKeyPem = pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) Goose.Generator.Logf(4, "PEM Certificate: %s", crtkit.ServerCertPem) return nil }
// 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 }
func (ca *CA) newCertificate(id string, pub *ecdsa.PublicKey, timestamp int64, opt ...pkix.Extension) ([]byte, error) { Trace.Println("creating certificate for " + id) notBefore := time.Now() notAfter := notBefore.Add(time.Hour * 24 * 90) isCA := ca.cert == nil tmpl := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ CommonName: "OBC", Organization: []string{"IBM"}, Country: []string{"US"}, }, NotBefore: notBefore, NotAfter: notAfter, SubjectKeyId: []byte{1, 2, 3, 4}, SignatureAlgorithm: x509.ECDSAWithSHA384, KeyUsage: x509.KeyUsageDigitalSignature, BasicConstraintsValid: true, IsCA: isCA, } if len(opt) > 0 { tmpl.Extensions = opt tmpl.ExtraExtensions = opt } parent := ca.cert if isCA { parent = &tmpl } raw, err := x509.CreateCertificate( rand.Reader, &tmpl, parent, pub, ca.priv, ) if isCA && err != nil { Panic.Panicln(err) } hash := sha3.New384() hash.Write(raw) if _, err = ca.db.Exec("INSERT INTO Certificates (id, timestamp, cert, hash) VALUES (?, ?, ?, ?)", id, timestamp, raw, hash.Sum(nil)); err != nil { if isCA { Panic.Panicln(err) } else { Error.Println(err) } } return raw, err }
// CreateGenericCRL is a helper function that takes in all of the information above, and then calls the createCRL // function. This outputs the bytes of the created CRL. func CreateGenericCRL(certList []pkix.RevokedCertificate, key crypto.Signer, issuingCert *x509.Certificate, expiryTime time.Time) ([]byte, error) { crlBytes, err := issuingCert.CreateCRL(rand.Reader, key, certList, time.Now(), expiryTime) if err != nil { log.Debug("error creating CRL: %s", err) } return crlBytes, err }
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 TestCheckCert(t *testing.T) { testKey, _ := rsa.GenerateKey(rand.Reader, 1024) checker := newChecker(nil) fc := clock.NewFake() fc.Add(time.Hour * 24 * 90) checker.clock = fc issued := checker.clock.Now().Add(-time.Hour * 24 * 45) goodExpiry := issued.Add(checkPeriod) serial := big.NewInt(1337) // Problems // Blacklsited common name // Expiry period is too long // Basic Constraints aren't set // Wrong key usage (none) rawCert := x509.Certificate{ Subject: pkix.Name{ CommonName: "example.com", }, NotAfter: goodExpiry.AddDate(0, 0, 1), // Period too long DNSNames: []string{"example-a.com"}, SerialNumber: serial, BasicConstraintsValid: false, } brokenCertDer, err := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) test.AssertNotError(t, err, "Couldn't create certificate") // Problems // Digest doesn't match // Serial doesn't match // Expiry doesn't match cert := core.Certificate{ Status: core.StatusValid, DER: brokenCertDer, Issued: issued, Expires: goodExpiry.AddDate(0, 0, 2), // Expiration doesn't match } problems := checker.checkCert(cert) test.AssertEquals(t, len(problems), 7) // Fix the problems rawCert.Subject.CommonName = "example-a.com" rawCert.NotAfter = goodExpiry rawCert.BasicConstraintsValid = true rawCert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth} goodCertDer, err := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) test.AssertNotError(t, err, "Couldn't create certificate") parsed, err := x509.ParseCertificate(goodCertDer) test.AssertNotError(t, err, "Couldn't parse created certificate") cert.Serial = core.SerialToString(serial) cert.Digest = core.Fingerprint256(goodCertDer) cert.DER = goodCertDer cert.Expires = parsed.NotAfter problems = checker.checkCert(cert) test.AssertEquals(t, len(problems), 0) }
func generateCertificate(c certificateConfig) ([]byte, *rsa.PrivateKey, error) { serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return nil, nil, err } key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, nil, err } // Generate the subject key ID derEncodedPubKey, err := x509.MarshalPKIXPublicKey(&key.PublicKey) if err != nil { return nil, nil, err } pubKeyHash := sha1.New() pubKeyHash.Write(derEncodedPubKey) template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Kubernetes"}, }, NotBefore: notBefore, NotAfter: notAfter, IsCA: c.isCA, KeyUsage: c.keyUsage, ExtKeyUsage: c.extKeyUsage, BasicConstraintsValid: true, SubjectKeyId: pubKeyHash.Sum(nil), } if c.hosts[0] != "" { template.Subject.CommonName = c.hosts[0] } if c.isCA { c.caCert = &template c.caKey = key } for _, h := range c.hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } derBytes, err := x509.CreateCertificate(rand.Reader, &template, c.caCert, &key.PublicKey, c.caKey) if err != nil { return nil, nil, err } return derBytes, key, nil }
func Verify(options x509.VerifyOptions, cert *x509.Certificate) Result { result := Result{Certificate: cert} chains, err := cert.Verify(options) result.Error = err for _, chain := range chains { result.Chains = append(result.Chains, CommonNamesFromChain(chain)) } return result }
// setHosts parses the comma separated host name / IP list and adds them to Subject Alternate Name list of a server/hosting certificate. func setHosts(host string, cert *x509.Certificate) { hosts := strings.Split(host, ",") for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { cert.IPAddresses = append(cert.IPAddresses, ip) } else { cert.DNSNames = append(cert.DNSNames, h) } } }
// GenerateTestCerts generate certs for testing or hacking func GenerateTestCerts() (*Certs, error) { priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, err } 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 { return nil, 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, } template.DNSNames = append(template.DNSNames, "example.com") derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return nil, err } var cbuf bytes.Buffer pem.Encode(&cbuf, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) var kbuf bytes.Buffer pem.Encode(&kbuf, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) privateKey, err := crypto.ParseRSAPrivateKeyFromPEM(kbuf.Bytes()) if err != nil { return nil, err } publicKey, err := crypto.ParseRSAPublicKeyFromPEM(cbuf.Bytes()) if err != nil { return nil, err } return &Certs{PrivateKey: privateKey, PublicKey: publicKey}, nil }
// You may also specify additional subject alt names (either ip or dns names) for the certificate // The certificate will be created with file mode 0644. The key will be created with file mode 0600. // If the certificate or key files already exist, they will be overwritten. // Any parent directories of the certPath or keyPath will be created as needed with file mode 0755. func GenerateSelfSignedCert(certPath, keyPath string, ips []net.IP, alternateDNS []string) error { priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return err } template := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ CommonName: "minishift", }, NotBefore: time.Now(), NotAfter: time.Now().Add(time.Hour * 24 * 365), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, IsCA: true, } template.IPAddresses = append(template.IPAddresses, ips...) template.DNSNames = append(template.DNSNames, alternateDNS...) derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return err } certBuffer := bytes.Buffer{} if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { return err } keyBuffer := bytes.Buffer{} if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { return err } if err := os.MkdirAll(filepath.Dir(certPath), os.FileMode(0755)); err != nil { return err } if err := ioutil.WriteFile(certPath, certBuffer.Bytes(), os.FileMode(0644)); err != nil { return err } if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil { return err } if err := ioutil.WriteFile(keyPath, keyBuffer.Bytes(), os.FileMode(0600)); err != nil { return err } 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 }
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 }
// Verify operates on an X509Store and validates the existence of a chain of trust // between a leafCertificate and a CA present inside of the X509 Store. // It requires at least two certificates in certList, a leaf Certificate and an // intermediate CA certificate. func Verify(s X509Store, dnsName string, certList []*x509.Certificate) error { // If we have no Certificates loaded return error (we don't want to revert to using // system CAs). if len(s.GetCertificates()) == 0 { return errors.New("no root CAs available") } // At a minimum we should be provided a leaf cert and an intermediate. if len(certList) < 2 { return errors.New("certificate and at least one intermediate needed") } // Get the VerifyOptions from the keystore for a base dnsName opts, err := s.GetVerifyOptions(dnsName) if err != nil { return err } // Create a Certificate Pool for our intermediate certificates intPool := x509.NewCertPool() var leafCert *x509.Certificate // Iterate through all the certificates for _, c := range certList { // If the cert is a CA, we add it to the intermediates pool. If not, we call // it the leaf cert if c.IsCA { intPool.AddCert(c) continue } // Certificate is not a CA, it must be our leaf certificate. // If we already found one, bail with error if leafCert != nil { return errors.New("more than one leaf certificate found") } leafCert = c } // We exited the loop with no leaf certificates if leafCert == nil { return errors.New("no leaf certificates found") } // We have one leaf certificate and at least one intermediate. Lets add this // Cert Pool as the Intermediates list on our VerifyOptions opts.Intermediates = intPool // Finally, let's call Verify on our leafCert with our fully configured options chains, err := leafCert.Verify(opts) if len(chains) == 0 || err != nil { return fmt.Errorf("certificate verification failed: %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 (CertificateValidator) validateCertAndChain(certificate *x509.Certificate, certPool *x509.CertPool) error { opts := x509.VerifyOptions{ Roots: certPool, } if _, err := certificate.Verify(opts); err != nil { return fmt.Errorf("certificate and chain mismatch: %s", err.Error()) } return nil }
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 }
func verifyX509Cert(cert *x509.Certificate, dnsName string, roots *x509.CertPool) error { verifyOptions := x509.VerifyOptions{ DNSName: dnsName, Roots: roots, KeyUsages: []x509.ExtKeyUsage{ x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth, }, } _, err := cert.Verify(verifyOptions) return err }
func signHost(ca tls.Certificate, hosts []string) (cert tls.Certificate, err error) { var x509ca *x509.Certificate // Use the provided ca and not the global GoproxyCa for certificate generation. if x509ca, err = x509.ParseCertificate(ca.Certificate[0]); err != nil { return } start := time.Unix(0, 0) end, err := time.Parse("2006-01-02", "2049-12-31") if err != nil { panic(err) } hash := hashSorted(append(hosts, goproxySignerVersion, ":"+runtime.Version())) serial := new(big.Int) serial.SetBytes(hash) template := x509.Certificate{ // TODO(elazar): instead of this ugly hack, just encode the certificate and hash the binary form. SerialNumber: serial, Issuer: x509ca.Subject, Subject: pkix.Name{ Organization: []string{CertOrganisation}, }, NotBefore: start, NotAfter: end, 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) } } var csprng CounterEncryptorRand if csprng, err = NewCounterEncryptorRandFromKey(ca.PrivateKey, hash); err != nil { return } var certpriv *rsa.PrivateKey if certpriv, err = rsa.GenerateKey(&csprng, 1024); err != nil { return } var derBytes []byte if derBytes, err = x509.CreateCertificate(&csprng, &template, x509ca, &certpriv.PublicKey, ca.PrivateKey); err != nil { return } return tls.Certificate{ Certificate: [][]byte{derBytes, ca.Certificate[0]}, PrivateKey: certpriv, }, nil }
func (t trustPinChecker) caCheck(leafCert *x509.Certificate, intCerts []*x509.Certificate) bool { // Use intermediate certificates included in the root TUF metadata for our validation caIntPool := x509.NewCertPool() for _, intCert := range intCerts { caIntPool.AddCert(intCert) } // Attempt to find a valid certificate chain from the leaf cert to CA root // Use this certificate if such a valid chain exists (possibly using intermediates) if _, err := leafCert.Verify(x509.VerifyOptions{Roots: t.pinnedCAPool, Intermediates: caIntPool}); err == nil { return true } return false }
func CheckCertAgainRoot(x509Cert *x509.Certificate, certPool *x509.CertPool) ([][]*x509.Certificate, error) { opts := x509.VerifyOptions{ // TODO DNSName: "test.example.com", Roots: certPool, } return x509Cert.Verify(opts) }