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) }
// imitateCertificate returns a new TLS certificate that has most of the same // data as serverCert but is signed by Redwood's root certificate, or // self-signed. func imitateCertificate(serverCert *x509.Certificate, selfSigned bool, conf *config) (cert tls.Certificate, err error) { template := serverCert if selfSigned { template = &x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: serverCert.Subject, NotBefore: serverCert.NotBefore, NotAfter: serverCert.NotAfter, KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: serverCert.ExtKeyUsage, DNSNames: serverCert.DNSNames, } } else { // Use a hash of the real certificate as the serial number. h := md5.New() h.Write(serverCert.Raw) h.Write([]byte{1}) // To give different serial numbers after the key usage change. template.SerialNumber = big.NewInt(0).SetBytes(h.Sum(nil)) if err != nil { return tls.Certificate{}, fmt.Errorf("failed to generate serial number: %s", err) } template.SubjectKeyId = nil template.AuthorityKeyId = nil template.OCSPServer = nil template.IssuingCertificateURL = nil template.CRLDistributionPoints = nil template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment template.BasicConstraintsValid = false template.SignatureAlgorithm = x509.UnknownSignatureAlgorithm } var newCertBytes []byte if selfSigned { newCertBytes, err = x509.CreateCertificate(rand.Reader, template, template, conf.ParsedTLSCert.PublicKey, conf.TLSCert.PrivateKey) } else { newCertBytes, err = x509.CreateCertificate(rand.Reader, template, conf.ParsedTLSCert, conf.ParsedTLSCert.PublicKey, conf.TLSCert.PrivateKey) } if err != nil { return tls.Certificate{}, err } newCert := tls.Certificate{ Certificate: [][]byte{newCertBytes}, PrivateKey: conf.TLSCert.PrivateKey, } if !selfSigned { newCert.Certificate = append(newCert.Certificate, conf.TLSCert.Certificate...) } return newCert, nil }
//CreateUserCertificate create a simple self-signed cert func CreateUserCertificate(key *Key, username string, expires time.Time) (*Certificate, error) { certName := pkix.Name{ Country: nil, Organization: nil, OrganizationalUnit: []string{username}, Locality: nil, Province: nil, StreetAddress: nil, PostalCode: nil, SerialNumber: "", CommonName: "", } hostTemplate.Subject = certName hostTemplate.NotAfter = expires // hostTemplate.SubjectKeyId, err := GenerateSubjectKeyId(key.Public) // if err != nil { // return nil, err // } crtBytes, err := x509.CreateCertificate(rand.Reader, &hostTemplate, &hostTemplate, key.Public, key.Private) if err != nil { return nil, err } return NewCertificateFromDER(crtBytes), nil }
func NewSignedCertificate(cfg CertConfig, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) { serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) if err != nil { return nil, err } certTmpl := x509.Certificate{ Subject: pkix.Name{ CommonName: cfg.CommonName, Organization: caCert.Subject.Organization, }, DNSNames: cfg.AltNames.DNSNames, IPAddresses: cfg.AltNames.IPs, SerialNumber: serial, NotBefore: caCert.NotBefore, NotAfter: time.Now().Add(Duration365d).UTC(), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } certDERBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, caCert, key.Public(), caKey) if err != nil { return nil, err } return x509.ParseCertificate(certDERBytes) }
// GenerateServerCert generates a server certificate and returns the cert bytes as // well as the private key used to generate the certificate. // Takes in the CA cert and key, the size of the key to generate, and the list // of hosts/ip addresses this certificate applies to. func GenerateServerCert(caCert *x509.Certificate, caKey crypto.PrivateKey, keySize int, hosts []string) ( []byte, crypto.PrivateKey, error) { privateKey, publicKey, err := generateKeyPair(keySize) if err != nil { return nil, nil, err } template, err := newTemplate(NodeUser) if err != nil { return nil, nil, err } // Only server authentication is allowed. template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} if hosts != nil { for _, h := range hosts { if ip := net.ParseIP(h); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, h) } } } certBytes, err := x509.CreateCertificate(rand.Reader, template, caCert, publicKey, caKey) if err != nil { return nil, nil, err } return certBytes, privateKey, nil }
func generateDerCert(privKey *rsa.PrivateKey, expiration time.Time, domain string) ([]byte, error) { serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { return nil, err } if expiration.IsZero() { expiration = time.Now().Add(365) } template := x509.Certificate{ SerialNumber: serialNumber, Subject: pkix.Name{ CommonName: "ACME Challenge TEMP", }, NotBefore: time.Now(), NotAfter: expiration, KeyUsage: x509.KeyUsageKeyEncipherment, BasicConstraintsValid: true, DNSNames: []string{domain}, } return x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey) }
// Cert generates a new TLS certificate for hostname and signs it using caPrivKey. func Cert(t *testing.T, caCert *x509.Certificate, caPrivKey *ecdsa.PrivateKey, hostname string, rnd io.Reader) tls.Certificate { if rnd == nil { rnd = rand.Reader } privKey, err := ecdsa.GenerateKey(elliptic.P256(), rnd) if err != nil { t.Fatal(err) } certTemplate := &x509.Certificate{ Subject: pkix.Name{CommonName: hostname}, SerialNumber: newSerial(t, rnd), NotBefore: time.Now(), NotAfter: time.Now().Add(1 * time.Hour), KeyUsage: x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, } if ip := net.ParseIP(hostname); ip != nil { certTemplate.IPAddresses = []net.IP{ip} } certDER, err := x509.CreateCertificate(rnd, certTemplate, caCert, &privKey.PublicKey, caPrivKey) if err != nil { t.Fatal(err) } cert, err := x509.ParseCertificate(certDER) if err != nil { t.Fatal(err) } return tls.Certificate{Certificate: [][]byte{certDER}, PrivateKey: privKey, Leaf: cert} }
func generateCert(serverName string, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, *rsa.PrivateKey, error) { priv, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { return nil, nil, err } serial := randBigInt() keyId := randBytes() template := x509.Certificate{ Subject: pkix.Name{ CommonName: serverName, }, SerialNumber: serial, SubjectKeyId: keyId, AuthorityKeyId: caCert.AuthorityKeyId, NotBefore: time.Now().Add(-5 * time.Minute).UTC(), NotAfter: time.Now().AddDate(2, 0, 0).UTC(), } derBytes, err := x509.CreateCertificate(rand.Reader, &template, caCert, &priv.PublicKey, caKey) if err != nil { return nil, nil, err } certs, err := x509.ParseCertificates(derBytes) if err != nil { return nil, nil, err } if len(certs) != 1 { return nil, nil, errors.New("Failed to generate a parsable certificate") } return certs[0], priv, nil }
// generateKeyAndCert deals with the creation and storage of a key and returns a cert func generateKeyAndCert(gun string) (crypto.PrivateKey, *x509.Certificate, error) { // Generates a new RSA key key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, nil, fmt.Errorf("could not generate private key: %v", err) } // Creates a new Certificate template. We need the certificate to calculate the // TUF-compliant keyID //TODO (diogo): We're hardcoding the Organization to be the GUN. Probably want to // change it template := newCertificate(gun, gun) derBytes, err := x509.CreateCertificate(rand.Reader, template, template, key.Public(), key) if err != nil { return nil, nil, fmt.Errorf("failed to generate the certificate for key: %v", err) } // Encode the new certificate into PEM cert, err := x509.ParseCertificate(derBytes) if err != nil { return nil, nil, fmt.Errorf("failed to generate the certificate for key: %v", err) } fingerprint := trustmanager.FingerprintCert(cert) // The key is going to be stored in the private directory, using the GUN and // the filename will be the TUF-compliant ID. The Store takes care of extensions. privKeyFilename := filepath.Join(gun, fingerprint) pemKey, err := trustmanager.KeyToPEM(key) if err != nil { return nil, nil, fmt.Errorf("failed to generate the certificate for key: %v", err) } return key, cert, privKeyStore.Add(privKeyFilename, pemKey) }
// Hijack takes a net.Conn and the host name to create the SSL // certificate for and returns a tls.Conn that can read and write // to the given host over TLS. func (mitm *MITM) Hijack(conn net.Conn, host string) (*tls.Conn, *bufio.ReadWriter, error) { // Ensure the certificate we create is valid within a window of time to allow // for clock skew. start := time.Now().Add(-mitm.Validity) end := time.Now().Add(mitm.Validity) tpl, err := NewTemplate(mitm.Organization, host, start, end, mitm.PublicKey) if err != nil { return nil, nil, err } cb, err := x509.CreateCertificate(rand.Reader, tpl, mitm.Authority, mitm.PublicKey, mitm.PrivateKey) if err != nil { return nil, nil, err } config := &tls.Config{ Certificates: []tls.Certificate{ { PrivateKey: mitm.PrivateKey, Certificate: [][]byte{cb}, }, }, } tlsConn := tls.Server(conn, config) r := bufio.NewReader(tlsConn) w := bufio.NewWriter(tlsConn) return tlsConn, bufio.NewReadWriter(r, w), nil }
// NewCA generates a CA certificate/key pair suitable for signing server // keys for an environment with the given name. func NewCA(envName string, expiry time.Time) (certPEM, keyPEM string, err error) { key, err := rsa.GenerateKey(rand.Reader, KeyBits) if err != nil { return "", "", err } now := time.Now() template := &x509.Certificate{ SerialNumber: new(big.Int), Subject: pkix.Name{ CommonName: fmt.Sprintf("juju-generated CA for environment %q", envName), Organization: []string{"juju"}, }, NotBefore: now.UTC().AddDate(0, 0, -7), NotAfter: expiry.UTC(), SubjectKeyId: bigIntHash(key.N), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, IsCA: true, MaxPathLen: 0, // Disallow delegation for now. BasicConstraintsValid: true, } certDER, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key) if err != nil { return "", "", fmt.Errorf("cannot create certificate: %v", err) } certPEMData := pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: certDER, }) keyPEMData := pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key), }) return string(certPEMData), string(keyPEMData), nil }
// newLeaf generates a certificate/key pair suitable for use by a leaf node. func newLeaf(caCertPEM, caKeyPEM string, expiry time.Time, hostnames []string, extKeyUsage []x509.ExtKeyUsage) (certPEM, keyPEM string, err error) { tlsCert, err := tls.X509KeyPair([]byte(caCertPEM), []byte(caKeyPEM)) if err != nil { return "", "", err } if len(tlsCert.Certificate) != 1 { return "", "", fmt.Errorf("more than one certificate for CA") } caCert, err := x509.ParseCertificate(tlsCert.Certificate[0]) if err != nil { return "", "", err } if !caCert.BasicConstraintsValid || !caCert.IsCA { return "", "", fmt.Errorf("CA certificate is not a valid CA") } caKey, ok := tlsCert.PrivateKey.(*rsa.PrivateKey) if !ok { return "", "", fmt.Errorf("CA private key has unexpected type %T", tlsCert.PrivateKey) } key, err := rsa.GenerateKey(rand.Reader, KeyBits) if err != nil { return "", "", fmt.Errorf("cannot generate key: %v", err) } now := time.Now() template := &x509.Certificate{ SerialNumber: new(big.Int), Subject: pkix.Name{ // This won't match host names with dots. The hostname // is hardcoded when connecting to avoid the issue. CommonName: "*", Organization: []string{"juju"}, }, NotBefore: now.UTC().AddDate(0, 0, -7), NotAfter: expiry.UTC(), SubjectKeyId: bigIntHash(key.N), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement, ExtKeyUsage: extKeyUsage, } for _, hostname := range hostnames { if ip := net.ParseIP(hostname); ip != nil { template.IPAddresses = append(template.IPAddresses, ip) } else { template.DNSNames = append(template.DNSNames, hostname) } } certDER, err := x509.CreateCertificate(rand.Reader, template, caCert, &key.PublicKey, caKey) if err != nil { return "", "", err } certPEMData := pem.EncodeToMemory(&pem.Block{ Type: "CERTIFICATE", Bytes: certDER, }) keyPEMData := pem.EncodeToMemory(&pem.Block{ Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key), }) return string(certPEMData), string(keyPEMData), nil }
// CreateSignedX509 creates a signed X.509 certificate based on a template. func (s *Signer) CreateSignedX509(subject *Verifier, template, issuer *x509.Certificate) (*x509.Certificate, error) { der, err := x509.CreateCertificate(rand.Reader, template, issuer, subject.ec, s.ec) if err != nil { return nil, err } return x509.ParseCertificate(der) }
// generateFromTemplate generates a certificate from the given template and signed by // the given parent, storing the results in a certificate and key file. func generateFromTemplate(certFile, keyFile string, template, parent *x509.Certificate, key crypto.PrivateKey, parentKey crypto.PrivateKey) error { derBytes, err := x509.CreateCertificate(rand.Reader, template, parent, key.(crypto.Signer).Public(), parentKey) if err != nil { return err } certOut, err := os.Create(certFile) if err != nil { return err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() keyOut, err := os.OpenFile(keyFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { return err } defer keyOut.Close() switch v := key.(type) { case *rsa.PrivateKey: keyBytes := x509.MarshalPKCS1PrivateKey(v) pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: keyBytes}) case *ecdsa.PrivateKey: keyBytes, err := x509.MarshalECPrivateKey(v) if err != nil { return err } pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}) default: return fmt.Errorf("Unsupport private key type: %#v", key) } return nil }
// generateCA creates a new CA certificate, saves the certificate // and returns the x509 certificate and crypto private key. This // private key should never be saved to disk, but rather used to // immediately generate further certificates. func generateCA(caFile string) (*x509.Certificate, crypto.PrivateKey, error) { template := newCertificate() template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign template.Subject.CommonName = org priv, err := newPrivateKey() if err != nil { return nil, nil, err } derBytes, err := x509.CreateCertificate(rand.Reader, template, template, priv.(crypto.Signer).Public(), priv) if err != nil { return nil, nil, err } ca, err := x509.ParseCertificate(derBytes) if err != nil { return nil, nil, err } certOut, err := os.Create(caFile) if err != nil { return nil, nil, err } defer certOut.Close() if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { return nil, nil, err } return ca, priv, nil }
// GenerateCA generates a new certificate authority // and stores the resulting certificate and key file // in the arguments. func GenerateCA(certFile, keyFile string) error { log.Printf("Generating a new certificate authority.") template := newCertificate() template.IsCA = true template.KeyUsage |= x509.KeyUsageCertSign priv, err := rsa.GenerateKey(rand.Reader, RSABITS) if err != nil { return err } derBytes, err := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv) if err != nil { return err } certOut, err := os.Create(certFile) if err != nil { return err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() keyOut, err := os.OpenFile(keyFile, 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 }
// makeCert creates a self-signed RSA certificate. // taken from crypto/tls/generate_cert.go func makeCert(host string, validFor time.Duration) (certPEM, keyPEM []byte) { const bits = 1024 priv, err := rsa.GenerateKey(rand.Reader, bits) if err != nil { log.Fatalf("Failed to generate private key: %s", err) } template := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ Organization: []string{"Fabio Co"}, }, NotBefore: time.Now(), NotAfter: time.Now().Add(validFor), IsCA: true, DNSNames: []string{host}, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { log.Fatalf("Failed to create certificate: %s", err) } var cert, key bytes.Buffer pem.Encode(&cert, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) pem.Encode(&key, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) return cert.Bytes(), key.Bytes() }
func GenerateEmptyConfig() (*tls.Config, error) { priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { return nil, err } number, err := rand.Int(rand.Reader, big.NewInt(0).Lsh(big.NewInt(1), 128)) if err != nil { return nil, err } cert := &x509.Certificate{ SerialNumber: number, NotBefore: time.Now(), NotAfter: time.Now().Add(time.Hour * 24), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, } certbytes, err := x509.CreateCertificate(rand.Reader, cert, cert, &priv.PublicKey, priv) if err != nil { return nil, err } ct := tls.Certificate{[][]byte{certbytes}, priv, nil, cert} c := &tls.Config{InsecureSkipVerify: true} c.Certificates = append(c.Certificates, ct) c.NextProtos = []string{Proto} return c, nil }
// CA returns a new CA certificate, a pool containing that certificate, and the // corresponding private key. func CA(t *testing.T, rnd io.Reader) (*x509.Certificate, *x509.CertPool, *ecdsa.PrivateKey) { if rnd == nil { rnd = rand.Reader } var err error caPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rnd) if err != nil { t.Fatal(err) } caCertTemplate := &x509.Certificate{ Subject: pkix.Name{CommonName: "testingCA"}, SerialNumber: newSerial(t, rnd), NotBefore: time.Now(), NotAfter: time.Now().Add(time.Hour), KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, IsCA: true, MaxPathLen: 4, } caCertDER, err := x509.CreateCertificate(rnd, caCertTemplate, caCertTemplate, &caPrivKey.PublicKey, caPrivKey) if err != nil { t.Fatal(err) } caCert, err := x509.ParseCertificate(caCertDER) if err != nil { t.Fatal(err) } caPool := x509.NewCertPool() caPool.AddCert(caCert) return caCert, caPool, caPrivKey }
// CreateCertificateAuthority creates Certificate Authority using existing key. // CertificateAuthorityInfo returned is the extra infomation required by Certificate Authority. func CreateCertificateAuthority(key *Key, organizationalUnit string, years int, organization string, country string, province string, locality string, commonName string) (*Certificate, error) { subjectKeyID, err := GenerateSubjectKeyID(key.Public) if err != nil { return nil, err } authTemplate.SubjectKeyId = subjectKeyID authTemplate.NotAfter = time.Now().AddDate(years, 0, 0).UTC() if len(country) > 0 { authTemplate.Subject.Country = []string{country} } if len(province) > 0 { authTemplate.Subject.Province = []string{province} } if len(locality) > 0 { authTemplate.Subject.Locality = []string{locality} } if len(organization) > 0 { authTemplate.Subject.Organization = []string{organization} } if len(organizationalUnit) > 0 { authTemplate.Subject.OrganizationalUnit = []string{organizationalUnit} } if len(commonName) > 0 { authTemplate.Subject.CommonName = commonName } crtBytes, err := x509.CreateCertificate(rand.Reader, &authTemplate, &authTemplate, key.Public, key.Private) if err != nil { return nil, err } return NewCertificateFromDER(crtBytes), nil }
// GenerateCertificate generates an X509 Certificate from a template, given a GUN func GenerateCertificate(rootKey data.PrivateKey, gun string) (*x509.Certificate, error) { switch rootKey.(type) { case *data.RSAPrivateKey, *data.ECDSAPrivateKey: // go doesn't fall through default: return nil, fmt.Errorf("only bare RSA or ECDSA keys (not x509 variants) are currently supported. Found: %s", rootKey.Algorithm()) } template, err := trustmanager.NewCertificate(gun) if err != nil { return nil, fmt.Errorf("failed to create the certificate template for: %s (%v)", gun, err) } derBytes, err := x509.CreateCertificate(rand.Reader, template, template, rootKey.CryptoSigner().Public(), rootKey.CryptoSigner()) if err != nil { return nil, fmt.Errorf("failed to create the certificate for: %s (%v)", gun, err) } // Encode the new certificate into PEM cert, err := x509.ParseCertificate(derBytes) if err != nil { return nil, fmt.Errorf("failed to parse the certificate for key: %s (%v)", gun, err) } return cert, nil }
func NewSelfSignedCACertificate(cfg CertConfig, key *rsa.PrivateKey, validDuration time.Duration) (*x509.Certificate, error) { now := time.Now() dur := Duration365d * 10 if validDuration != 0 { dur = validDuration } tmpl := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), Subject: pkix.Name{ CommonName: cfg.CommonName, Organization: cfg.Organization, }, NotBefore: now, NotAfter: now.Add(dur), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, IsCA: true, } certDERBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, key.Public(), key) if err != nil { return nil, err } return x509.ParseCertificate(certDERBytes) }
func BenchmarkCheckCert(b *testing.B) { dbMap, err := sa.NewDbMap(dbConnStr) if err != nil { fmt.Println("Couldn't connect to database") return } checker := newChecker(dbMap) testKey, _ := rsa.GenerateKey(rand.Reader, 1024) expiry := time.Now().AddDate(0, 0, 1) serial := big.NewInt(1337) rawCert := x509.Certificate{ Subject: pkix.Name{ CommonName: "example.com", }, NotAfter: expiry, DNSNames: []string{"example-a.com"}, SerialNumber: serial, } certDer, _ := x509.CreateCertificate(rand.Reader, &rawCert, &rawCert, &testKey.PublicKey, testKey) cert := core.Certificate{ Status: core.StatusValid, Serial: core.SerialToString(serial), Digest: core.Fingerprint256(certDer), DER: certDer, Issued: time.Now(), Expires: expiry, } b.ResetTimer() for i := 0; i < b.N; i++ { checker.checkCert(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 }
// GenerateCA generates a CA certificate and returns the cert bytes as // well as the private key used to generate the certificate. func GenerateCA(keySize int) ([]byte, crypto.PrivateKey, error) { privateKey, publicKey, err := generateKeyPair(keySize) if err != nil { return nil, nil, err } template, err := newTemplate(caCommonName) if err != nil { return nil, nil, err } // Set CA-specific fields. template.BasicConstraintsValid = true template.IsCA = true template.MaxPathLen = maxPathLength template.KeyUsage |= x509.KeyUsageCertSign template.KeyUsage |= x509.KeyUsageContentCommitment certBytes, err := x509.CreateCertificate(rand.Reader, template, template, publicKey, privateKey) if err != nil { return nil, nil, err } return certBytes, privateKey, nil }
// generates a multiple-certificate file with both RSA and ECDSA certs and // returns the filename so that cleanup can be deferred. func generateMultiCert(t *testing.T) string { tempFile, err := ioutil.TempFile("/tmp", "cert-test") defer tempFile.Close() assert.NoError(t, err) rsaKey, err := rsa.GenerateKey(rand.Reader, 2048) assert.NoError(t, err) ecKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) assert.NoError(t, err) template, err := trustmanager.NewCertificate("gun") assert.NoError(t, err) for _, key := range []crypto.Signer{rsaKey, ecKey} { derBytes, err := x509.CreateCertificate( rand.Reader, template, template, key.Public(), key) assert.NoError(t, err) cert, err := x509.ParseCertificate(derBytes) assert.NoError(t, err) pemBytes := trustmanager.CertToPEM(cert) nBytes, err := tempFile.Write(pemBytes) assert.NoError(t, err) assert.Equal(t, nBytes, len(pemBytes)) } return tempFile.Name() }
// GenerateClientCert generates a client certificate and returns the cert bytes as // well as the private key used to generate the certificate. // The CA cert and private key should be passed in. // 'user' is the unique username stored in the Subject.CommonName field. func GenerateClientCert(caCert *x509.Certificate, caKey crypto.PrivateKey, keySize int, name string) ( []byte, crypto.PrivateKey, error) { privateKey, publicKey, err := generateKeyPair(keySize) if err != nil { return nil, nil, err } // TODO(marc): should we add extra checks? if len(name) == 0 { return nil, nil, util.Errorf("name cannot be empty") } template, err := newTemplate(name) if err != nil { return nil, nil, err } // Set client-specific fields. // Client authentication only. template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} certBytes, err := x509.CreateCertificate(rand.Reader, template, caCert, publicKey, caKey) if err != nil { return nil, nil, err } return certBytes, privateKey, 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 }
func DetermineKeyIDFromPublicKey(pubk crypto.PublicKey) (string, error) { // Trick crypto/x509 into creating a certificate so we can grab the // subjectPublicKeyInfo by giving it a fake private key generating an invalid // signature. ParseCertificate doesn't verify the signature so this will // work. // // Yes, this is very hacky, but avoids having to duplicate code in crypto/x509. determineKeyIDFromKeyIntl(pubk, psuedoPrivateKey{}) cc := &x509.Certificate{ SerialNumber: big.NewInt(1), } cb, err := x509.CreateCertificate(rand.Reader, cc, cc, pubk, &psuedoPrivateKey{pubk}) if err != nil { return "", err } c, err := x509.ParseCertificate(cb) if err != nil { return "", err } return determineKeyIDFromCert(c), nil }
func generateCert(privKey *rsa.PrivateKey, domain string) ([]byte, error) { 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{ CommonName: "ACME Challenge TEMP", }, NotBefore: time.Now(), NotAfter: time.Now().Add(365), KeyUsage: x509.KeyUsageKeyEncipherment, BasicConstraintsValid: true, DNSNames: []string{domain}, } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey) if err != nil { return nil, err } return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil }