Ejemplo n.º 1
0
// 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)
}
Ejemplo n.º 2
0
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.")
				}
			}
		}
	}

}
Ejemplo n.º 3
0
// 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

}
Ejemplo n.º 4
0
// parseCertificateRequest takes an incoming certificate request and
// builds a certificate template from it.
func parseCertificateRequest(priv crypto.Signer, csrBytes []byte) (template *x509.Certificate, err error) {

	csr, err := x509.ParseCertificateRequest(csrBytes)
	if err != nil {
		err = cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
		return
	}

	err = signer.CheckSignature(csr, csr.SignatureAlgorithm, csr.RawTBSCertificateRequest, csr.Signature)
	if err != nil {
		err = cferr.Wrap(cferr.CertificateError, cferr.KeyMismatch, err)
		return
	}

	template = &x509.Certificate{
		Subject:            csr.Subject,
		PublicKeyAlgorithm: csr.PublicKeyAlgorithm,
		PublicKey:          csr.PublicKey,
		SignatureAlgorithm: signer.DefaultSigAlgo(priv),
	}

	return
}
Ejemplo n.º 5
0
// New returns a new PKCS #11 signer.
func New(caCertFile string, policy *config.Signing, cfg *pkcs11key.Config) (signer.Signer, error) {
	if cfg == nil {
		return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
	}

	log.Debugf("Loading PKCS #11 module %s", cfg.Module)
	certData, err := ioutil.ReadFile(caCertFile)
	if err != nil {
		return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
	}

	cert, err := helpers.ParseCertificatePEM(certData)
	if err != nil {
		return nil, err
	}

	priv, err := pkcs11key.New(cfg.Module, cfg.TokenLabel, cfg.PIN, cfg.PrivateKeyLabel)
	if err != nil {
		return nil, errors.New(errors.PrivateKeyError, errors.ReadFailed)
	}
	sigAlgo := signer.DefaultSigAlgo(priv)

	return local.NewSigner(priv, cert, sigAlgo, policy)
}
Ejemplo n.º 6
0
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)
			}
		}

	}
}
Ejemplo n.º 7
0
// 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
}