func loadKey(keyConfig cmd.KeyConfig) (priv crypto.Signer, err error) { if keyConfig.File != "" { var keyBytes []byte keyBytes, err = ioutil.ReadFile(keyConfig.File) if err != nil { return nil, fmt.Errorf("Could not read key file %s", keyConfig.File) } priv, err = helpers.ParsePrivateKeyPEM(keyBytes) return } pkcs11Config := keyConfig.PKCS11 if pkcs11Config.Module == "" || pkcs11Config.TokenLabel == "" || pkcs11Config.PIN == "" || pkcs11Config.PrivateKeyLabel == "" || pkcs11Config.SlotID == nil { err = fmt.Errorf("Missing a field in pkcs11Config %#v", pkcs11Config) return } priv, err = pkcs11key.New(pkcs11Config.Module, pkcs11Config.TokenLabel, pkcs11Config.PIN, pkcs11Config.PrivateKeyLabel, *pkcs11Config.SlotID) return }
// NewSignerFromFile generates a new local signer from a caFile // and a caKey file, both PEM encoded. func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signer, error) { log.Debug("Loading CA: ", caFile) ca, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } log.Debug("Loading CA key: ", caKeyFile) cakey, err := ioutil.ReadFile(caKeyFile) if err != nil { return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err) } parsedCa, err := helpers.ParseCertificatePEM(ca) if err != nil { return nil, err } priv, err := helpers.ParsePrivateKeyPEM(cakey) if err != nil { log.Debug("Malformed private key %v", err) return nil, err } return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy) }
// NewSignerFromFile reads the issuer cert, the responder cert and the responder key // from PEM files, and takes an interval in seconds func NewSignerFromFile(issuerFile, responderFile, keyFile string, interval time.Duration) (Signer, error) { log.Debug("Loading issuer cert: ", issuerFile) issuerBytes, err := ioutil.ReadFile(issuerFile) if err != nil { return nil, err } log.Debug("Loading responder cert: ", responderFile) responderBytes, err := ioutil.ReadFile(responderFile) if err != nil { return nil, err } log.Debug("Loading responder key: ", keyFile) keyBytes, err := ioutil.ReadFile(keyFile) if err != nil { return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err) } issuerCert, err := helpers.ParseCertificatePEM(issuerBytes) if err != nil { return nil, err } responderCert, err := helpers.ParseCertificatePEM(responderBytes) if err != nil { return nil, err } key, err := helpers.ParsePrivateKeyPEM(keyBytes) if err != nil { log.Debug("Malformed private key %v", err) return nil, err } return NewSigner(issuerCert, responderCert, key, interval) }
func TestReGenerate(t *testing.T) { var req = &CertificateRequest{ Names: []Name{ { C: "US", ST: "California", L: "San Francisco", O: "CloudFlare", OU: "Systems Engineering", }, }, CN: "cloudflare.com", Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1"}, KeyRequest: &BasicKeyRequest{"ecdsa", 256}, } csr, key, err := ParseRequest(req) if err != nil { t.Fatalf("%v", err) } priv, err := helpers.ParsePrivateKeyPEM(key) if err != nil { t.Fatalf("%v", err) } csr, err = Generate(priv, req) if err != nil { t.Fatalf("%v", err) } if _, _, err = helpers.ParseCSR(csr); err != nil { t.Fatalf("%v", err) } }
func loadPrivateKey(keyConfig cmd.KeyConfig) (crypto.Signer, error) { if keyConfig.File != "" { keyBytes, err := ioutil.ReadFile(keyConfig.File) if err != nil { return nil, fmt.Errorf("Could not read key file %s", keyConfig.File) } return helpers.ParsePrivateKeyPEM(keyBytes) } var pkcs11Config *pkcs11key.Config if keyConfig.ConfigFile != "" { contents, err := ioutil.ReadFile(keyConfig.ConfigFile) if err != nil { return nil, err } pkcs11Config = new(pkcs11key.Config) err = json.Unmarshal(contents, pkcs11Config) if err != nil { return nil, err } } else { pkcs11Config = keyConfig.PKCS11 } if pkcs11Config.Module == "" || pkcs11Config.TokenLabel == "" || pkcs11Config.PIN == "" || pkcs11Config.PrivateKeyLabel == "" { return nil, fmt.Errorf("Missing a field in pkcs11Config %#v", pkcs11Config) } return pkcs11key.New(pkcs11Config.Module, pkcs11Config.TokenLabel, pkcs11Config.PIN, pkcs11Config.PrivateKeyLabel) }
func TestCAIssuing(t *testing.T) { var caCerts = []string{testCaFile, testECDSACaFile} var caKeys = []string{testCaKeyFile, testECDSACaKeyFile} var interCSRs = []string{ecdsaInterCSR, rsaInterCSR} var interKeys = []string{ecdsaInterKey, rsaInterKey} var CAPolicy = &config.Signing{ Default: &config.SigningProfile{ Usage: []string{"cert sign", "crl sign"}, ExpiryString: "1h", Expiry: 1 * time.Hour, CA: true, }, } var hostname = "cloudflare-inter.com" // Each RSA or ECDSA root CA issues two intermediate CAs (one ECDSA and one RSA). // For each intermediate CA, use it to issue additional RSA and ECDSA intermediate CSRs. for i, caFile := range caCerts { caKeyFile := caKeys[i] s := newCustomSigner(t, caFile, caKeyFile) s.policy = CAPolicy for j, csr := range interCSRs { csrBytes, _ := ioutil.ReadFile(csr) certBytes, err := s.Sign(signer.SignRequest{Hosts: signer.SplitHosts(hostname), Request: string(csrBytes)}) if err != nil { t.Fatal(err) } interCert, err := helpers.ParseCertificatePEM(certBytes) if err != nil { t.Fatal(err) } keyBytes, _ := ioutil.ReadFile(interKeys[j]) interKey, _ := helpers.ParsePrivateKeyPEM(keyBytes) interSigner := &Signer{interCert, interKey, CAPolicy, signer.DefaultSigAlgo(interKey)} for _, anotherCSR := range interCSRs { anotherCSRBytes, _ := ioutil.ReadFile(anotherCSR) bytes, err := interSigner.Sign( signer.SignRequest{ Hosts: signer.SplitHosts(hostname), Request: string(anotherCSRBytes), }) if err != nil { t.Fatal(err) } cert, err := helpers.ParseCertificatePEM(bytes) if err != nil { t.Fatal(err) } if cert.SignatureAlgorithm != interSigner.SigAlgo() { t.Fatal("Cert Signature Algorithm does not match the issuer.") } } } } }
func init() { var err error caKey, err = helpers.ParsePrivateKeyPEM(mustRead(caKeyFile)) if err != nil { panic(fmt.Sprintf("Unable to parse %s: %s", caKeyFile, err)) } caCert, err = core.LoadCert(caCertFile) if err != nil { panic(fmt.Sprintf("Unable to parse %s: %s", caCertFile, err)) } }
func loadIssuerKey(filename string) (issuerKey crypto.Signer, err error) { if filename == "" { err = errors.New("IssuerKey must be provided in test mode.") return } pem, err := ioutil.ReadFile(filename) if err != nil { return } issuerKey, err = helpers.ParsePrivateKeyPEM(pem) return }
func loadKey(keyConfig KeyConfig) (priv crypto.Signer, err error) { if keyConfig.File != "" { var keyBytes []byte keyBytes, err = ioutil.ReadFile(keyConfig.File) if err != nil { return nil, fmt.Errorf("Could not read key file %s", keyConfig.File) } priv, err = helpers.ParsePrivateKeyPEM(keyBytes) return } pkcs11Config := keyConfig.PKCS11 priv, err = pkcs11key.New(pkcs11Config.Module, pkcs11Config.Token, pkcs11Config.PIN, pkcs11Config.Label) return }
func TestMain(m *testing.M) { caKeyPEM, _ := ioutil.ReadFile(caKeyFile) caKey, _ := helpers.ParsePrivateKeyPEM(caKeyPEM) caCertPEM, _ := ioutil.ReadFile(caCertFile) caCert, _ := helpers.ParseCertificatePEM(caCertPEM) // Create an online CFSSL instance // This is designed to mimic what LE plans to do authHandler, _ := auth.New(authKey, nil) policy := &cfsslConfig.Signing{ Profiles: map[string]*cfsslConfig.SigningProfile{ profileName: &cfsslConfig.SigningProfile{ Usage: []string{"server auth"}, CA: false, IssuerURL: []string{"http://not-example.com/issuer-url"}, OCSP: "http://not-example.com/ocsp", CRL: "http://not-example.com/crl", Policies: []asn1.ObjectIdentifier{ asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1}, }, Expiry: 8760 * time.Hour, Backdate: time.Hour, Provider: authHandler, CSRWhitelist: &cfsslConfig.CSRWhitelist{ PublicKeyAlgorithm: true, PublicKey: true, SignatureAlgorithm: true, }, }, }, Default: &cfsslConfig.SigningProfile{ Expiry: time.Hour, }, } cfsslSigner, _ = local.NewSigner(caKey, caCert, x509.SHA256WithRSA, policy) signHandler, _ := apisign.NewAuthHandlerFromSigner(cfsslSigner) http.Handle("/api/v1/cfssl/authsign", signHandler) // This goroutine should get killed when main() return go (func() { http.ListenAndServe(hostPort, nil) })() os.Exit(m.Run()) }
// New creates a new root certificate from the certificate request. func New(req *csr.CertificateRequest) (cert, key []byte, err error) { if req.CA != nil { if req.CA.Expiry != "" { CAPolicy.Default.ExpiryString = req.CA.Expiry CAPolicy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry) } if req.CA.PathLength != 0 { signer.MaxPathLen = req.CA.PathLength } } g := &csr.Generator{Validator: validator} csr, key, err := g.ProcessRequest(req) if err != nil { log.Errorf("failed to process request: %v", err) key = nil return } priv, err := helpers.ParsePrivateKeyPEM(key) if err != nil { log.Errorf("failed to parse private key: %v", err) return } s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil) if err != nil { log.Errorf("failed to create signer: %v", err) return } s.SetPolicy(CAPolicy) signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csr)} cert, err = s.Sign(signReq) return }
// BundleFromPEM builds a certificate bundle from the set of byte // slices containing the PEM-encoded certificate(s), private key. func (b *Bundler) BundleFromPEM(certsPEM, keyPEM []byte, flavor BundleFlavor) (*Bundle, error) { log.Debug("bundling from PEM files") var key crypto.Signer var err error if len(keyPEM) != 0 { key, err = helpers.ParsePrivateKeyPEM(keyPEM) if err != nil { log.Debugf("failed to parse private key: %v", err) return nil, err } } certs, err := helpers.ParseCertificatesPEM(certsPEM) if err != nil { log.Debugf("failed to parse certificates: %v", err) return nil, err } else if len(certs) == 0 { log.Debugf("no certificates found") return nil, errors.New(errors.CertificateError, errors.DecodeFailed) } log.Debugf("bundle ready") return b.Bundle(certs, key, flavor) }
func selfSignMain(args []string, c cli.Config) (err error) { if c.Hostname == "" && !c.IsCA { c.Hostname, args, err = cli.PopFirstArgument(args) if err != nil { return } } csrFile, args, err := cli.PopFirstArgument(args) if err != nil { return } csrFileBytes, err := cli.ReadStdin(csrFile) if err != nil { return } var req csr.CertificateRequest err = json.Unmarshal(csrFileBytes, &req) if err != nil { return } var key, csrPEM []byte g := &csr.Generator{Validator: genkey.Validator} csrPEM, key, err = g.ProcessRequest(&req) if err != nil { key = nil return } priv, err := helpers.ParsePrivateKeyPEM(key) if err != nil { key = nil return } var profile *config.SigningProfile // If there is a config, use its signing policy. Otherwise, leave policy == nil // and NewSigner will use DefaultConfig(). if c.CFG != nil { if c.Profile != "" && c.CFG.Signing.Profiles != nil { profile = c.CFG.Signing.Profiles[c.Profile] } } if profile == nil { profile = config.DefaultConfig() profile.Expiry = 2190 * time.Hour } cert, err := selfsign.Sign(priv, csrPEM, profile) if err != nil { key = nil priv = nil return } fmt.Fprintf(os.Stderr, `*** WARNING *** Self-signed certificates are dangerous. Use this self-signed certificate at your own risk. It is strongly recommended that these certificates NOT be used in production. *** WARNING *** `) cli.PrintCert(key, csrPEM, cert) return }
func TestInitCA(t *testing.T) { var req *csr.CertificateRequest hostname := "cloudflare.com" for _, param := range validKeyParams { req = &csr.CertificateRequest{ Names: []csr.Name{ { C: "US", ST: "California", L: "San Francisco", O: "CloudFlare", OU: "Systems Engineering", }, }, CN: hostname, Hosts: []string{hostname, "www." + hostname}, KeyRequest: &csr.KeyRequest{ Algo: param.keyAlgo, Size: param.keyLen, }, } certBytes, keyBytes, err := New(req) if err != nil { t.Fatal("InitCA failed:", err) } key, err := helpers.ParsePrivateKeyPEM(keyBytes) if err != nil { t.Fatal("InitCA private key parsing failed:", err) } cert, err := helpers.ParseCertificatePEM(certBytes) if err != nil { t.Fatal("InitCA cert parsing failed:", err) } // Verify key parameters. switch req.KeyRequest.Algo { case "rsa": if cert.PublicKey.(*rsa.PublicKey).N.BitLen() != param.keyLen { t.Fatal("Cert key length mismatch.") } if key.(*rsa.PrivateKey).N.BitLen() != param.keyLen { t.Fatal("Private key length mismatch.") } case "ecdsa": if cert.PublicKey.(*ecdsa.PublicKey).Curve.Params().BitSize != param.keyLen { t.Fatal("Cert key length mismatch.") } if key.(*ecdsa.PrivateKey).Curve.Params().BitSize != param.keyLen { t.Fatal("Private key length mismatch.") } } // Start a signer var CAPolicy = &config.Signing{ Default: &config.SigningProfile{ Usage: []string{"cert sign", "crl sign"}, ExpiryString: "300s", Expiry: 300 * time.Second, CA: true, }, } s, err := local.NewSigner(key, cert, signer.DefaultSigAlgo(key), nil) if err != nil { t.Fatal("Signer Creation error:", err) } s.SetPolicy(CAPolicy) // Sign RSA and ECDSA customer CSRs. for _, csrFile := range csrFiles { csrBytes, err := ioutil.ReadFile(csrFile) if err != nil { t.Fatal("CSR loading error:", err) } req := signer.SignRequest{ Request: string(csrBytes), Hosts: signer.SplitHosts(hostname), Profile: "", Label: "", } bytes, err := s.Sign(req) if err != nil { t.Fatal(err) } customerCert, _ := helpers.ParseCertificatePEM(bytes) if customerCert.SignatureAlgorithm != s.SigAlgo() { t.Fatal("Signature Algorithm mismatch") } err = customerCert.CheckSignatureFrom(cert) if err != nil { t.Fatal("Signing CSR failed.", err) } } } }
// NewFromPEM creates a new root certificate from the key file passed in. func NewFromPEM(req *csr.CertificateRequest, keyFile string) (cert []byte, err error) { if req.CA != nil { if req.CA.Expiry != "" { CAPolicy.Default.ExpiryString = req.CA.Expiry CAPolicy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry) } if req.CA.PathLength != 0 { signer.MaxPathLen = req.CA.PathLength } } privData, err := ioutil.ReadFile(keyFile) if err != nil { return nil, err } priv, err := helpers.ParsePrivateKeyPEM(privData) if err != nil { return nil, err } var sigAlgo x509.SignatureAlgorithm switch priv := priv.(type) { case *rsa.PrivateKey: bitLength := priv.PublicKey.N.BitLen() switch { case bitLength >= 4096: sigAlgo = x509.SHA512WithRSA case bitLength >= 3072: sigAlgo = x509.SHA384WithRSA case bitLength >= 2048: sigAlgo = x509.SHA256WithRSA default: sigAlgo = x509.SHA1WithRSA } case *ecdsa.PrivateKey: switch priv.Curve { case elliptic.P521(): sigAlgo = x509.ECDSAWithSHA512 case elliptic.P384(): sigAlgo = x509.ECDSAWithSHA384 case elliptic.P256(): sigAlgo = x509.ECDSAWithSHA256 default: sigAlgo = x509.ECDSAWithSHA1 } default: sigAlgo = x509.UnknownSignatureAlgorithm } var tpl = x509.CertificateRequest{ Subject: req.Name(), SignatureAlgorithm: sigAlgo, DNSNames: req.Hosts, } certReq, err := x509.CreateCertificateRequest(rand.Reader, &tpl, priv) if err != nil { log.Errorf("failed to generate a CSR: %v", err) // The use of CertificateError was a matter of some // debate; it is the one edge case in which a new // error category specifically for CSRs might be // useful, but it was deemed that one edge case did // not a new category justify. err = cferr.Wrap(cferr.CertificateError, cferr.BadRequest, err) return } p := &pem.Block{ Type: "CERTIFICATE REQUEST", Bytes: certReq, } certReq = pem.EncodeToMemory(p) s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), nil) if err != nil { log.Errorf("failed to create signer: %v", err) return } s.SetPolicy(CAPolicy) signReq := signer.SignRequest{Request: string(certReq)} cert, err = s.Sign(signReq) return }