예제 #1
0
// jwsEncodeJSON signs claimset using provided key and a nonce.
// The result is serialized in JSON format.
// See https://tools.ietf.org/html/rfc7515#section-7.
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
	jwk, err := jwkEncode(key.Public())
	if err != nil {
		return nil, err
	}
	phead := fmt.Sprintf(`{"alg":"RS256","jwk":%s,"nonce":%q}`, jwk, nonce)
	phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
	cs, err := json.Marshal(claimset)
	if err != nil {
		return nil, err
	}
	payload := base64.RawURLEncoding.EncodeToString(cs)
	h := sha256.New()
	h.Write([]byte(phead + "." + payload))
	sig, err := key.Sign(rand.Reader, h.Sum(nil), crypto.SHA256)
	if err != nil {
		return nil, err
	}
	enc := struct {
		Protected string `json:"protected"`
		Payload   string `json:"payload"`
		Sig       string `json:"signature"`
	}{
		Protected: phead,
		Payload:   payload,
		Sig:       base64.RawURLEncoding.EncodeToString(sig),
	}
	return json.Marshal(&enc)
}
예제 #2
0
파일: jws.go 프로젝트: Rudloff/platform
// jwsEncodeJSON signs claimset using provided key and a nonce.
// The result is serialized in JSON format.
// See https://tools.ietf.org/html/rfc7515#section-7.
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
	jwk, err := jwkEncode(key.Public())
	if err != nil {
		return nil, err
	}
	alg, sha := jwsHasher(key)
	if alg == "" || !sha.Available() {
		return nil, ErrUnsupportedKey
	}
	phead := fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q}`, alg, jwk, nonce)
	phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
	cs, err := json.Marshal(claimset)
	if err != nil {
		return nil, err
	}
	payload := base64.RawURLEncoding.EncodeToString(cs)
	hash := sha.New()
	hash.Write([]byte(phead + "." + payload))
	sig, err := jwsSign(key, sha, hash.Sum(nil))
	if err != nil {
		return nil, err
	}

	enc := struct {
		Protected string `json:"protected"`
		Payload   string `json:"payload"`
		Sig       string `json:"signature"`
	}{
		Protected: phead,
		Payload:   payload,
		Sig:       base64.RawURLEncoding.EncodeToString(sig),
	}
	return json.Marshal(&enc)
}
예제 #3
0
파일: server.go 프로젝트: vsayer/gokeyless
// Add adds a new key to the server's internal repertoire.
// Stores in maps by SKI and (if possible) Digest, SNI, Server IP, and Client IP.
func (keys *defaultKeystore) Add(op *gokeyless.Operation, priv crypto.Signer) error {
	ski, err := gokeyless.GetSKI(priv.Public())
	if err != nil {
		return err
	}

	keys.Lock()
	defer keys.Unlock()

	if digest, err := gokeyless.GetDigest(priv.Public()); err == nil {
		keys.digests[digest] = ski
	}

	if op != nil {
		if op.SNI != "" {
			keys.snis[op.SNI] = ski
		}
		if op.ServerIP != nil {
			keys.serverIPs[op.ServerIP.String()] = ski
		}
		if op.ClientIP != nil {
			keys.clientIPs[op.ClientIP.String()] = ski
		}
		keys.validAKIs[ski] = keys.validAKIs[ski].Add(op.AKI)
	}

	keys.skis[ski] = priv

	log.Debugf("Adding key with SKI: %02x", ski)
	return nil
}
예제 #4
0
파일: signer.go 프로젝트: mclem/cfssl
// DefaultSigAlgo returns an appropriate X.509 signature algorithm given
// the CA's private key.
func DefaultSigAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
	pub := priv.Public()
	switch pub := pub.(type) {
	case *rsa.PublicKey:
		keySize := pub.N.BitLen()
		switch {
		case keySize >= 4096:
			return x509.SHA512WithRSA
		case keySize >= 3072:
			return x509.SHA384WithRSA
		case keySize >= 2048:
			return x509.SHA256WithRSA
		default:
			return x509.SHA1WithRSA
		}
	case *ecdsa.PublicKey:
		switch pub.Curve {
		case elliptic.P256():
			return x509.ECDSAWithSHA256
		case elliptic.P384():
			return x509.ECDSAWithSHA384
		case elliptic.P521():
			return x509.ECDSAWithSHA512
		default:
			return x509.ECDSAWithSHA1
		}
	default:
		return x509.UnknownSignatureAlgorithm
	}
}
예제 #5
0
파일: keys.go 프로젝트: C0rWin/fabric
// NewSignerFromSigner takes any crypto.Signer implementation and
// returns a corresponding Signer interface. This can be used, for
// example, with keys kept in hardware modules.
func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
	pubKey, err := NewPublicKey(signer.Public())
	if err != nil {
		return nil, err
	}

	return &wrappedSigner{signer, pubKey}, nil
}
예제 #6
0
func generateCertificate(t *testing.T, signer crypto.Signer, out io.Writer) {
	derBytes, err := x509.CreateCertificate(rand.Reader, &certTemplate, &certTemplate, signer.Public(), signer)
	if err != nil {
		t.Fatal("Unable to generate a certificate", err.Error())
	}

	if err = pem.Encode(out, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
		t.Fatal("Unable to write cert to file", err.Error())
	}
}
예제 #7
0
파일: helpers.go 프로젝트: citywander/vault
// GetSubjKeyID returns the subject key ID, e.g. the SHA1 sum
// of the marshaled public key
func GetSubjKeyID(privateKey crypto.Signer) ([]byte, error) {
	if privateKey == nil {
		return nil, InternalError{"passed-in private key is nil"}
	}

	marshaledKey, err := x509.MarshalPKIXPublicKey(privateKey.Public())
	if err != nil {
		return nil, InternalError{fmt.Sprintf("error marshalling public key: %s", err)}
	}

	subjKeyID := sha1.Sum(marshaledKey)

	return subjKeyID[:], nil
}
예제 #8
0
// SignerAlgo returns an X.509 signature algorithm corresponding to
// the crypto.Hash provided from a crypto.Signer.
func SignerAlgo(priv crypto.Signer, h crypto.Hash) x509.SignatureAlgorithm {
	switch priv.Public().(type) {
	case *rsa.PublicKey:
		switch h {
		case crypto.SHA512:
			return x509.SHA512WithRSA
		case crypto.SHA384:
			return x509.SHA384WithRSA
		case crypto.SHA256:
			return x509.SHA256WithRSA
		default:
			return x509.SHA1WithRSA
		}
	case *ecdsa.PublicKey:
		switch h {
		case crypto.SHA512:
			return x509.ECDSAWithSHA512
		case crypto.SHA384:
			return x509.ECDSAWithSHA384
		case crypto.SHA256:
			return x509.ECDSAWithSHA256
		default:
			return x509.ECDSAWithSHA1
		}
	default:
		return x509.UnknownSignatureAlgorithm
	}
}
예제 #9
0
// NewFromSigner creates a new root certificate from a crypto.Signer.
func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPEM []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 err != nil {
				return nil, nil, err
			}
		}

		if req.CA.PathLength != 0 {
			signer.MaxPathLen = req.CA.PathLength
		}
	}

	var sigAlgo x509.SignatureAlgorithm
	switch pub := priv.Public().(type) {
	case *rsa.PublicKey:
		bitLength := pub.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.PublicKey:
		switch pub.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,
	}

	for i := range req.Hosts {
		if ip := net.ParseIP(req.Hosts[i]); ip != nil {
			tpl.IPAddresses = append(tpl.IPAddresses, ip)
		} else {
			tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
		}
	}

	return signWithCSR(&tpl, priv)
}
예제 #10
0
파일: acme.go 프로젝트: 40a/ejson
// tlsChallengeCert creates a temporary certificate for TLS-SNI challenges
// with the given SANs and auto-generated public/private key pair.
// To create a cert with a custom key pair, specify WithKey option.
func tlsChallengeCert(san []string, opt []CertOption) (tls.Certificate, error) {
	var (
		key  crypto.Signer
		tmpl *x509.Certificate
	)
	for _, o := range opt {
		switch o := o.(type) {
		case *certOptKey:
			if key != nil {
				return tls.Certificate{}, errors.New("acme: duplicate key option")
			}
			key = o.key
		case *certOptTemplate:
			var t = *(*x509.Certificate)(o) // shallow copy is ok
			tmpl = &t
		default:
			// package's fault, if we let this happen:
			panic(fmt.Sprintf("unsupported option type %T", o))
		}
	}
	if key == nil {
		var err error
		if key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader); err != nil {
			return tls.Certificate{}, err
		}
	}
	if tmpl == nil {
		tmpl = &x509.Certificate{
			SerialNumber:          big.NewInt(1),
			NotBefore:             time.Now(),
			NotAfter:              time.Now().Add(24 * time.Hour),
			BasicConstraintsValid: true,
			KeyUsage:              x509.KeyUsageKeyEncipherment,
		}
	}
	tmpl.DNSNames = san

	der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, key.Public(), key)
	if err != nil {
		return tls.Certificate{}, err
	}
	return tls.Certificate{
		Certificate: [][]byte{der},
		PrivateKey:  key,
	}, nil
}
예제 #11
0
// RegisterKey adds a new key to the server's internal repertoire.
func (s *Server) RegisterKey(key crypto.Signer) error {
	ski, err := gokeyless.GetSKI(key.Public())
	if err != nil {
		return err
	}

	s.Lock()
	defer s.Unlock()

	if digest, ok := gokeyless.GetDigest(key.Public()); ok {
		s.digests[digest] = ski
	}
	s.keys[ski] = key

	s.Log.Printf("Registering key with SKI: %X", ski)
	return nil
}
예제 #12
0
func generateCertificate(signer crypto.Signer, gun string, startTime, endTime time.Time) (*x509.Certificate, error) {
	template, err := trustmanager.NewCertificate(gun, startTime, endTime)
	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, signer.Public(), signer)
	if err != nil {
		return nil, fmt.Errorf("failed to create the certificate for: %s (%v)", gun, err)
	}

	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
}
예제 #13
0
파일: private_key.go 프로젝트: 40a/ejson
// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that
// implements RSA or ECDSA.
func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
	pk := new(PrivateKey)
	switch pubkey := signer.Public().(type) {
	case rsa.PublicKey:
		pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
		pk.PubKeyAlgo = PubKeyAlgoRSASignOnly
	case ecdsa.PublicKey:
		pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
	default:
		panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
	}
	pk.PrivateKey = signer
	return pk
}
예제 #14
0
// RenewFromSigner re-creates a root certificate from the CA cert and crypto.Signer.
// The resulting root certificate will have ca certificate
// as the template and have the same expiry length. E.g. the exsiting CA
// is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate
// will be valid from now and expire in one year as well.
func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) {
	if !ca.IsCA {
		return nil, errors.New("input certificate is not a CA cert")
	}

	// matching certificate public key vs private key
	switch {
	case ca.PublicKeyAlgorithm == x509.RSA:

		var rsaPublicKey *rsa.PublicKey
		var ok bool
		if rsaPublicKey, ok = priv.Public().(*rsa.PublicKey); !ok {
			return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
		}
		if ca.PublicKey.(*rsa.PublicKey).N.Cmp(rsaPublicKey.N) != 0 {
			return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
		}
	case ca.PublicKeyAlgorithm == x509.ECDSA:
		var ecdsaPublicKey *ecdsa.PublicKey
		var ok bool
		if ecdsaPublicKey, ok = priv.Public().(*ecdsa.PublicKey); !ok {
			return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
		}
		if ca.PublicKey.(*ecdsa.PublicKey).X.Cmp(ecdsaPublicKey.X) != 0 {
			return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
		}
	default:
		return nil, cferr.New(cferr.PrivateKeyError, cferr.NotRSAOrECC)
	}

	req := csr.ExtractCertificateRequest(ca)

	cert, _, err := NewFromSigner(req, priv)
	return cert, err

}
예제 #15
0
// NewSignTests generates a map of test name to TestFunc that performs an opaque sign and verify.
func NewSignTests(priv crypto.Signer) map[string]testapi.TestFunc {
	tests := make(map[string]testapi.TestFunc)
	ptxt := []byte("Test Plaintext")
	r := rand.Reader
	hashes := map[string]crypto.Hash{
		"sign.md5sha1": crypto.MD5SHA1,
		"sign.sha1":    crypto.SHA1,
		"sign.sha224":  crypto.SHA224,
		"sign.sha256":  crypto.SHA256,
		"sign.sha384":  crypto.SHA384,
		"sign.sha512":  crypto.SHA512,
	}

	for hashName, h := range hashes {
		var msg []byte
		if h == crypto.MD5SHA1 {
			msg = append(hashPtxt(crypto.MD5, ptxt), hashPtxt(crypto.SHA1, ptxt)...)
		} else {
			msg = hashPtxt(h, ptxt)
		}

		tests[hashName] = func(h crypto.Hash) testapi.TestFunc {
			return func() error {
				sig, err := priv.Sign(r, msg, h)
				if err != nil {
					return err
				}

				switch pub := priv.Public().(type) {
				case *rsa.PublicKey:
					return rsa.VerifyPKCS1v15(pub, h, msg, sig)
				case *ecdsa.PublicKey:
					ecdsaSig := new(struct{ R, S *big.Int })
					asn1.Unmarshal(sig, ecdsaSig)
					if !ecdsa.Verify(pub, msg, ecdsaSig.R, ecdsaSig.S) {
						return errors.New("ecdsa verify failed")
					}
				default:
					return errors.New("unknown public key type")
				}

				return nil
			}
		}(h)
	}
	return tests
}
예제 #16
0
func (s *Server) handle(conn *gokeyless.Conn) {
	defer conn.Close()
	s.Log.Println("Handling new connection...")
	// Continuosly read request Headers from conn and respond
	// until a connection error (Read/Write failure) is encountered.
	var connError error
	for connError == nil {
		conn.SetDeadline(time.Now().Add(time.Hour))

		var h *gokeyless.Header
		if h, connError = conn.ReadHeader(); connError != nil {
			continue
		}

		s.Log.Printf("version:%d.%d id:%d body:%s", h.MajorVers, h.MinorVers, h.ID, h.Body)

		var opts crypto.SignerOpts
		var isRSA bool
		var key crypto.Signer
		var ok bool
		switch h.Body.Opcode {
		case gokeyless.OpPing:
			connError = conn.RespondPong(h.ID, h.Body.Payload)
			continue

		case gokeyless.OpRSADecrypt:
			if key, ok = s.getKey(h.Body.SKI, h.Body.Digest); !ok {
				s.Log.Println(gokeyless.ErrKeyNotFound)
				connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
				continue
			}

			if _, ok = key.Public().(*rsa.PublicKey); !ok {
				s.Log.Printf("%s: Key is not RSA\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				continue
			}

			rsaKey, ok := key.(crypto.Decrypter)
			if !ok {
				s.Log.Printf("%s: Key is not Decrypter\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				continue
			}

			ptxt, err := rsaKey.Decrypt(nil, h.Body.Payload, nil)
			if err != nil {
				s.Log.Printf("%s: Decryption error: %v", gokeyless.ErrCrypto, err)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				continue
			}

			connError = conn.Respond(h.ID, ptxt)
			continue
		case gokeyless.OpRSASignMD5SHA1:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignMD5SHA1:
			opts = crypto.MD5SHA1
		case gokeyless.OpRSASignSHA1:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA1:
			opts = crypto.SHA1
		case gokeyless.OpRSASignSHA224:
		case gokeyless.OpECDSASignSHA224:
			opts = crypto.SHA224
		case gokeyless.OpRSASignSHA256:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA256:
			opts = crypto.SHA256
		case gokeyless.OpRSASignSHA384:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA384:
			opts = crypto.SHA384
		case gokeyless.OpRSASignSHA512:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA512:
			opts = crypto.SHA512
		case gokeyless.OpPong:
			fallthrough
		case gokeyless.OpResponse:
			fallthrough
		case gokeyless.OpError:
			s.Log.Printf("%s: %s is not a valid request Opcode\n", gokeyless.ErrUnexpectedOpcode, h.Body.Opcode)
			connError = conn.RespondError(h.ID, gokeyless.ErrUnexpectedOpcode)
			continue
		default:
			connError = conn.RespondError(h.ID, gokeyless.ErrBadOpcode)
			continue
		}

		if key, ok = s.getKey(h.Body.SKI, h.Body.Digest); !ok {
			s.Log.Println(gokeyless.ErrKeyNotFound)
			connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
			continue
		}

		// Ensure we don't perform an ECDSA sign for an RSA request.
		if _, ok := key.Public().(*rsa.PublicKey); isRSA && !ok {
			s.Log.Printf("%s: request is RSA, but key is ECDSA\n", gokeyless.ErrCrypto)
			connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
			continue
		}

		sig, err := key.Sign(rand.Reader, h.Body.Payload, opts)
		if err != nil {
			s.Log.Printf("%s: Signing error: %v\n", gokeyless.ErrCrypto, err)
			connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
			continue
		}

		connError = conn.Respond(h.ID, sig)
	}
	s.Log.Printf("Connection error: %v\n", connError)
	return
}
예제 #17
0
// Performs the heavy lifting of creating a certificate. Returns
// a fully-filled-in ParsedCertBundle.
func createCertificate(creationInfo *certCreationBundle) (*certutil.ParsedCertBundle, error) {
	var clientPrivKey crypto.Signer
	var err error
	result := &certutil.ParsedCertBundle{}

	var serialNumber *big.Int
	serialNumber, err = rand.Int(rand.Reader, (&big.Int{}).Exp(big.NewInt(2), big.NewInt(159), nil))
	if err != nil {
		return nil, certutil.InternalError{Err: fmt.Sprintf("Error getting random serial number")}
	}

	switch creationInfo.KeyType {
	case "rsa":
		result.PrivateKeyType = certutil.RSAPrivateKey
		clientPrivKey, err = rsa.GenerateKey(rand.Reader, creationInfo.KeyBits)
		if err != nil {
			return nil, certutil.InternalError{Err: fmt.Sprintf("Error generating RSA private key")}
		}
		result.PrivateKey = clientPrivKey
		result.PrivateKeyBytes = x509.MarshalPKCS1PrivateKey(clientPrivKey.(*rsa.PrivateKey))
	case "ec":
		result.PrivateKeyType = certutil.ECPrivateKey
		var curve elliptic.Curve
		switch creationInfo.KeyBits {
		case 224:
			curve = elliptic.P224()
		case 256:
			curve = elliptic.P256()
		case 384:
			curve = elliptic.P384()
		case 521:
			curve = elliptic.P521()
		default:
			return nil, certutil.UserError{Err: fmt.Sprintf("Unsupported bit length for EC key: %d", creationInfo.KeyBits)}
		}
		clientPrivKey, err = ecdsa.GenerateKey(curve, rand.Reader)
		if err != nil {
			return nil, certutil.InternalError{Err: fmt.Sprintf("Error generating EC private key")}
		}
		result.PrivateKey = clientPrivKey
		result.PrivateKeyBytes, err = x509.MarshalECPrivateKey(clientPrivKey.(*ecdsa.PrivateKey))
		if err != nil {
			return nil, certutil.InternalError{Err: fmt.Sprintf("Error marshalling EC private key")}
		}
	default:
		return nil, certutil.UserError{Err: fmt.Sprintf("Unknown key type: %s", creationInfo.KeyType)}
	}

	subjKeyID, err := certutil.GetSubjKeyID(result.PrivateKey)
	if err != nil {
		return nil, certutil.InternalError{Err: fmt.Sprintf("Error getting subject key ID: %s", err)}
	}

	subject := pkix.Name{
		Country:            creationInfo.CACert.Subject.Country,
		Organization:       creationInfo.CACert.Subject.Organization,
		OrganizationalUnit: creationInfo.CACert.Subject.OrganizationalUnit,
		Locality:           creationInfo.CACert.Subject.Locality,
		Province:           creationInfo.CACert.Subject.Province,
		StreetAddress:      creationInfo.CACert.Subject.StreetAddress,
		PostalCode:         creationInfo.CACert.Subject.PostalCode,
		SerialNumber:       serialNumber.String(),
		CommonName:         creationInfo.CommonNames[0],
	}

	certTemplate := &x509.Certificate{
		SignatureAlgorithm:    x509.SHA256WithRSA,
		SerialNumber:          serialNumber,
		Subject:               subject,
		NotBefore:             time.Now(),
		NotAfter:              time.Now().Add(creationInfo.Lease),
		KeyUsage:              x509.KeyUsage(x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement),
		BasicConstraintsValid: true,
		IsCA:                        false,
		SubjectKeyId:                subjKeyID,
		DNSNames:                    creationInfo.CommonNames,
		IPAddresses:                 creationInfo.IPSANs,
		PermittedDNSDomainsCritical: false,
		PermittedDNSDomains:         nil,
		CRLDistributionPoints:       creationInfo.CACert.CRLDistributionPoints,
	}

	if creationInfo.Usage&serverUsage != 0 {
		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
	}
	if creationInfo.Usage&clientUsage != 0 {
		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
	}
	if creationInfo.Usage&codeSigningUsage != 0 {
		certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageCodeSigning)
	}

	cert, err := x509.CreateCertificate(rand.Reader, certTemplate, creationInfo.CACert, clientPrivKey.Public(), creationInfo.SigningBundle.PrivateKey)
	if err != nil {
		return nil, certutil.InternalError{Err: fmt.Sprintf("Unable to create certificate: %s", err)}
	}

	result.CertificateBytes = cert
	result.Certificate, err = x509.ParseCertificate(cert)
	if err != nil {
		return nil, certutil.InternalError{Err: fmt.Sprintf("Unable to parse created certificate: %s", err)}
	}

	result.IssuingCABytes = creationInfo.SigningBundle.CertificateBytes
	result.IssuingCA = creationInfo.SigningBundle.Certificate

	return result, nil
}
예제 #18
0
// CreateResponse returns a DER-encoded OCSP response with the specified contents.
// The fields in the response are populated as follows:
//
// The responder cert is used to populate the ResponderName field, and the certificate
// itself is provided alongside the OCSP response signature.
//
// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields.
// (SHA-1 is used for the hash function; this is not configurable.)
//
// The template is used to populate the SerialNumber, RevocationStatus, RevokedAt,
// RevocationReason, ThisUpdate, and NextUpdate fields.
//
// The ProducedAt date is automatically set to the current date, to the nearest minute.
func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) {
	var publicKeyInfo struct {
		Algorithm pkix.AlgorithmIdentifier
		PublicKey asn1.BitString
	}
	if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
		return nil, err
	}

	h := sha1.New()
	h.Write(publicKeyInfo.PublicKey.RightAlign())
	issuerKeyHash := h.Sum(nil)

	h.Reset()
	h.Write(issuer.RawSubject)
	issuerNameHash := h.Sum(nil)

	innerResponse := singleResponse{
		CertID: certID{
			HashAlgorithm: pkix.AlgorithmIdentifier{
				Algorithm:  hashOIDs[crypto.SHA1],
				Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
			},
			NameHash:      issuerNameHash,
			IssuerKeyHash: issuerKeyHash,
			SerialNumber:  template.SerialNumber,
		},
		ThisUpdate:       template.ThisUpdate.UTC(),
		NextUpdate:       template.NextUpdate.UTC(),
		SingleExtensions: template.ExtraExtensions,
	}

	switch template.Status {
	case Good:
		innerResponse.Good = true
	case Unknown:
		innerResponse.Unknown = true
	case Revoked:
		innerResponse.Revoked = revokedInfo{
			RevocationTime: template.RevokedAt.UTC(),
			Reason:         asn1.Enumerated(template.RevocationReason),
		}
	}

	responderName := asn1.RawValue{
		Class:      2, // context-specific
		Tag:        1, // explicit tag
		IsCompound: true,
		Bytes:      responderCert.RawSubject,
	}
	tbsResponseData := responseData{
		Version:          0,
		RawResponderName: responderName,
		ProducedAt:       time.Now().Truncate(time.Minute).UTC(),
		Responses:        []singleResponse{innerResponse},
	}

	tbsResponseDataDER, err := asn1.Marshal(tbsResponseData)
	if err != nil {
		return nil, err
	}

	hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
	if err != nil {
		return nil, err
	}

	responseHash := hashFunc.New()
	responseHash.Write(tbsResponseDataDER)
	signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc)
	if err != nil {
		return nil, err
	}

	response := basicResponse{
		TBSResponseData:    tbsResponseData,
		SignatureAlgorithm: signatureAlgorithm,
		Signature: asn1.BitString{
			Bytes:     signature,
			BitLength: 8 * len(signature),
		},
	}
	if template.Certificate != nil {
		response.Certificates = []asn1.RawValue{
			asn1.RawValue{FullBytes: template.Certificate.Raw},
		}
	}
	responseDER, err := asn1.Marshal(response)
	if err != nil {
		return nil, err
	}

	return asn1.Marshal(responseASN1{
		Status: asn1.Enumerated(Success),
		Response: responseBytes{
			ResponseType: idPKIXOCSPBasic,
			Response:     responseDER,
		},
	})
}
예제 #19
0
파일: bundler.go 프로젝트: hildjj/boulder
// Bundle takes an X509 certificate (already in the
// Certificate structure), a private key as crypto.Signer in one of the appropriate
// formats (i.e. *rsa.PrivateKey or *ecdsa.PrivateKey, or even a opaque key), using them to
// build a certificate bundle.
func (b *Bundler) Bundle(certs []*x509.Certificate, key crypto.Signer, flavor BundleFlavor) (*Bundle, error) {
	log.Infof("bundling certificate for %+v", certs[0].Subject)
	if len(certs) == 0 {
		return nil, nil
	}

	// Detect reverse ordering of the cert chain.
	if len(certs) > 1 && !partialVerify(certs) {
		rcerts := reverse(certs)
		if partialVerify(rcerts) {
			certs = rcerts
		}
	}

	var ok bool
	cert := certs[0]
	if key != nil {
		switch {
		case cert.PublicKeyAlgorithm == x509.RSA:

			var rsaPublicKey *rsa.PublicKey
			if rsaPublicKey, ok = key.Public().(*rsa.PublicKey); !ok {
				return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
			}
			if cert.PublicKey.(*rsa.PublicKey).N.Cmp(rsaPublicKey.N) != 0 {
				return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
			}
		case cert.PublicKeyAlgorithm == x509.ECDSA:
			var ecdsaPublicKey *ecdsa.PublicKey
			if ecdsaPublicKey, ok = key.Public().(*ecdsa.PublicKey); !ok {
				return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
			}
			if cert.PublicKey.(*ecdsa.PublicKey).X.Cmp(ecdsaPublicKey.X) != 0 {
				return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
			}
		default:
			return nil, errors.New(errors.PrivateKeyError, errors.NotRSAOrECC)
		}
	} else {
		switch {
		case cert.PublicKeyAlgorithm == x509.RSA:
		case cert.PublicKeyAlgorithm == x509.ECDSA:
		default:
			return nil, errors.New(errors.PrivateKeyError, errors.NotRSAOrECC)
		}
	}

	if cert.CheckSignatureFrom(cert) == nil {
		return nil, errors.New(errors.CertificateError, errors.SelfSigned)
	}

	bundle := new(Bundle)
	bundle.Cert = cert
	bundle.Key = key
	bundle.Issuer = &cert.Issuer
	bundle.Subject = &cert.Subject

	bundle.buildHostnames()

	// verify and store input intermediates to the intermediate pool.
	// Ignore the returned error here, will treat it in the second call.
	b.fetchIntermediates(certs)

	chains, err := cert.Verify(b.VerifyOptions())
	if err != nil {
		log.Debugf("verification failed: %v", err)
		// If the error was an unknown authority, try to fetch
		// the intermediate specified in the AIA and add it to
		// the intermediates bundle.
		switch err := err.(type) {
		case x509.UnknownAuthorityError:
			// Do nothing -- have the default case return out.
		default:
			return nil, errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
		}

		log.Debugf("searching for intermediates via AIA issuer")
		err = b.fetchIntermediates(certs)
		if err != nil {
			log.Debugf("search failed: %v", err)
			return nil, errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
		}

		log.Debugf("verifying new chain")
		chains, err = cert.Verify(b.VerifyOptions())
		if err != nil {
			log.Debugf("failed to verify chain: %v", err)
			return nil, errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
		}
		log.Debugf("verify ok")
	}
	var matchingChains [][]*x509.Certificate
	switch flavor {
	case Optimal:
		matchingChains = optimalChains(chains)
	case Ubiquitous:
		if len(ubiquity.Platforms) == 0 {
			log.Warning("No metadata, Ubiquitous falls back to Optimal.")
		}
		matchingChains = ubiquitousChains(chains)
	case Force:
		matchingChains = forceChains(certs, chains)
	default:
		matchingChains = ubiquitousChains(chains)
	}

	bundle.Chain = matchingChains[0]
	// Include at least one intermediate if the leaf has enabled OCSP and is not CA.
	if bundle.Cert.OCSPServer != nil && !bundle.Cert.IsCA && len(bundle.Chain) <= 2 {
		// No op. Return one intermediate if there is one.
	} else {
		// do not include the root.
		bundle.Chain = bundle.Chain[:len(bundle.Chain)-1]
	}

	statusCode := int(errors.Success)
	var messages []string
	// Check if bundle is expiring.
	expiringCerts := checkExpiringCerts(bundle.Chain)
	bundle.Expires = helpers.ExpiryTime(bundle.Chain)
	if len(expiringCerts) > 0 {
		statusCode |= errors.BundleExpiringBit
		messages = append(messages, expirationWarning(expiringCerts))
	}
	// Check if bundle contains SHA2 certs.
	if ubiquity.ChainHashUbiquity(matchingChains[0]) <= ubiquity.SHA2Ubiquity {
		statusCode |= errors.BundleNotUbiquitousBit
		messages = append(messages, sha2Warning)
	}
	// Check if bundle contains ECDSA signatures.
	if ubiquity.ChainKeyAlgoUbiquity(matchingChains[0]) <= ubiquity.ECDSA256Ubiquity {
		statusCode |= errors.BundleNotUbiquitousBit
		messages = append(messages, ecdsaWarning)
	}
	// Add root store presence info
	root := matchingChains[0][len(matchingChains[0])-1]
	bundle.Root = root
	log.Infof("the anchoring root is %v", root.Subject)
	// Check if there is any platform that doesn't trust the chain.
	// Also, an warning will be generated if ubiquity.Platforms is nil,
	untrusted := ubiquity.UntrustedPlatforms(root)
	untrustedMsg := untrustedPlatformsWarning(untrusted)
	if len(untrustedMsg) > 0 {
		log.Debug("Populate untrusted platform warning.")
		statusCode |= errors.BundleNotUbiquitousBit
		messages = append(messages, untrustedMsg)
	}
	// Check if there is any platform that rejects the chain because of SHA1 deprecation.
	deprecated := ubiquity.DeprecatedSHA1Platforms(matchingChains[0])
	if len(deprecated) > 0 {
		log.Debug("Populate SHA1 deprecation warning.")
		statusCode |= errors.BundleNotUbiquitousBit
		messages = append(messages, deprecateSHA1Warning(deprecated))
	}

	bundle.Status = &BundleStatus{ExpiringSKIs: getSKIs(bundle.Chain, expiringCerts), Code: statusCode, Messages: messages, Untrusted: untrusted}

	bundle.Status.IsRebundled = diff(bundle.Chain, certs)
	log.Debugf("bundle complete")
	return bundle, nil
}
예제 #20
0
파일: tests.go 프로젝트: Bren2010/gokeyless
// testKey performs and verifies all possible opaque private key operations.
func testKey(priv crypto.Signer) (err error) {
	ptxt := []byte("Test Plaintext")
	r := rand.Reader
	hashes := []crypto.Hash{
		crypto.MD5SHA1,
		crypto.SHA1,
		crypto.SHA224,
		crypto.SHA256,
		crypto.SHA384,
		crypto.SHA512,
	}

	for _, h := range hashes {
		var msg, sig []byte
		if h == crypto.MD5SHA1 {
			msg = append(hashPtxt(crypto.MD5, ptxt), hashPtxt(crypto.SHA1, ptxt)...)
		} else {
			msg = hashPtxt(h, ptxt)
		}

		if sig, err = priv.Sign(r, msg, h); err != nil {
			return
		}

		switch pub := priv.Public().(type) {
		case *rsa.PublicKey:
			if err = rsa.VerifyPKCS1v15(pub, h, msg, sig); err != nil {
				return
			}
		case *ecdsa.PublicKey:
			ecdsaSig := new(struct{ R, S *big.Int })
			asn1.Unmarshal(sig, ecdsaSig)
			if !ecdsa.Verify(pub, msg, ecdsaSig.R, ecdsaSig.S) {
				return errors.New("ecdsa verify failed")
			}
		default:
			return errors.New("unknown public key type")
		}
	}

	if pub, ok := priv.Public().(*rsa.PublicKey); ok {
		var c, m []byte
		if c, err = rsa.EncryptPKCS1v15(r, pub, ptxt); err != nil {
			return
		}

		var decrypter crypto.Decrypter
		if decrypter, ok = priv.(crypto.Decrypter); !ok {
			return errors.New("rsa public key but cannot decrypt")
		}

		if m, err = decrypter.Decrypt(r, c, &rsa.PKCS1v15DecryptOptions{}); err != nil {
			return
		}
		if bytes.Compare(ptxt, m) != 0 {
			return errors.New("rsa decrypt failed")
		}

		if m, err = decrypter.Decrypt(r, c, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: len(ptxt)}); err != nil {
			return
		}
		if bytes.Compare(ptxt, m) != 0 {
			return errors.New("rsa decrypt failed")
		}

		if m, err = decrypter.Decrypt(r, c, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: len(ptxt) + 1}); err != nil {
			return
		}
		if bytes.Compare(ptxt, m) == 0 {
			return errors.New("rsa decrypt suceeded despite incorrect SessionKeyLen")
		}
	}

	return nil
}
예제 #21
0
// NewRootCA creates a new RootCA object from unparsed cert and key byte
// slices. key may be nil, and in this case NewRootCA will return a RootCA
// without a signer.
func NewRootCA(cert, key []byte, certExpiry time.Duration) (RootCA, error) {
	// Check to see if the Certificate file is a valid, self-signed Cert
	parsedCA, err := helpers.ParseSelfSignedCertificatePEM(cert)
	if err != nil {
		return RootCA{}, err
	}

	// Calculate the digest for our RootCACertificate
	digest := digest.FromBytes(cert)

	// Create a Pool with our RootCACertificate
	pool := x509.NewCertPool()
	if !pool.AppendCertsFromPEM(cert) {
		return RootCA{}, fmt.Errorf("error while adding root CA cert to Cert Pool")
	}

	if len(key) == 0 {
		// This RootCA does not have a valid signer.
		return RootCA{Cert: cert, Digest: digest, Pool: pool}, nil
	}

	var (
		passphraseStr              string
		passphrase, passphrasePrev []byte
		priv                       crypto.Signer
	)

	// Attempt two distinct passphrases, so we can do a hitless passphrase rotation
	if passphraseStr = os.Getenv(PassphraseENVVar); passphraseStr != "" {
		passphrase = []byte(passphraseStr)
	}

	if p := os.Getenv(PassphraseENVVarPrev); p != "" {
		passphrasePrev = []byte(p)
	}

	// Attempt to decrypt the current private-key with the passphrases provided
	priv, err = helpers.ParsePrivateKeyPEMWithPassword(key, passphrase)
	if err != nil {
		priv, err = helpers.ParsePrivateKeyPEMWithPassword(key, passphrasePrev)
		if err != nil {
			log.Debug("Malformed private key %v", err)
			return RootCA{}, err
		}
	}

	if err := ensureCertKeyMatch(parsedCA, priv.Public()); err != nil {
		return RootCA{}, err
	}

	signer, err := local.NewSigner(priv, parsedCA, cfsigner.DefaultSigAlgo(priv), SigningPolicy(certExpiry))
	if err != nil {
		return RootCA{}, err
	}

	// If the key was loaded from disk unencrypted, but there is a passphrase set,
	// ensure it is encrypted, so it doesn't hit raft in plain-text
	keyBlock, _ := pem.Decode(key)
	if keyBlock == nil {
		// This RootCA does not have a valid signer.
		return RootCA{Cert: cert, Digest: digest, Pool: pool}, nil
	}
	if passphraseStr != "" && !x509.IsEncryptedPEMBlock(keyBlock) {
		key, err = EncryptECPrivateKey(key, passphraseStr)
		if err != nil {
			return RootCA{}, err
		}
	}

	return RootCA{Signer: signer, Key: key, Digest: digest, Cert: cert, Pool: pool}, nil
}
예제 #22
0
파일: server.go 프로젝트: vsayer/gokeyless
func (s *Server) handle(conn *gokeyless.Conn) {
	defer conn.Close()
	log.Debug("Handling new connection...")
	// Continuosly read request Headers from conn and respond
	// until a connection error (Read/Write failure) is encountered.
	var connError error
	for connError == nil {
		conn.SetDeadline(time.Now().Add(time.Hour))

		var h *gokeyless.Header
		if h, connError = conn.ReadHeader(); connError != nil {
			continue
		}

		requestBegin := time.Now()
		log.Debugf("version:%d.%d id:%d body:%s", h.MajorVers, h.MinorVers, h.ID, h.Body)

		var opts crypto.SignerOpts
		var key crypto.Signer
		var ok bool
		switch h.Body.Opcode {
		case gokeyless.OpPing:
			connError = conn.RespondPong(h.ID, h.Body.Payload)
			s.stats.logRequest(requestBegin)
			continue

		case gokeyless.OpRSADecrypt:
			if key, ok = s.Keys.Get(h.Body); !ok {
				log.Error(gokeyless.ErrKeyNotFound)
				connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
				s.stats.logInvalid(requestBegin)
				continue
			}

			if _, ok = key.Public().(*rsa.PublicKey); !ok {
				log.Errorf("%s: Key is not RSA\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}

			rsaKey, ok := key.(crypto.Decrypter)
			if !ok {
				log.Errorf("%s: Key is not Decrypter\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}

			ptxt, err := rsaKey.Decrypt(nil, h.Body.Payload, nil)
			if err != nil {
				log.Errorf("%s: Decryption error: %v", gokeyless.ErrCrypto, err)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}

			connError = conn.Respond(h.ID, ptxt)
			s.stats.logRequest(requestBegin)
			continue
		case gokeyless.OpRSASignMD5SHA1, gokeyless.OpECDSASignMD5SHA1:
			opts = crypto.MD5SHA1
		case gokeyless.OpRSASignSHA1, gokeyless.OpECDSASignSHA1:
			opts = crypto.SHA1
		case gokeyless.OpRSASignSHA224, gokeyless.OpECDSASignSHA224:
			opts = crypto.SHA224
		case gokeyless.OpRSASignSHA256, gokeyless.OpECDSASignSHA256:
			opts = crypto.SHA256
		case gokeyless.OpRSASignSHA384, gokeyless.OpECDSASignSHA384:
			opts = crypto.SHA384
		case gokeyless.OpRSASignSHA512, gokeyless.OpECDSASignSHA512:
			opts = crypto.SHA512
		case gokeyless.OpActivate:
			if len(s.ActivationToken) > 0 {
				hashedToken := sha256.Sum256(s.ActivationToken)
				connError = conn.Respond(h.ID, hashedToken[:])
				s.stats.logRequest(requestBegin)
			} else {
				connError = conn.RespondError(h.ID, gokeyless.ErrBadOpcode)
				s.stats.logInvalid(requestBegin)
			}
			continue
		case gokeyless.OpPong, gokeyless.OpResponse, gokeyless.OpError:
			log.Errorf("%s: %s is not a valid request Opcode\n", gokeyless.ErrUnexpectedOpcode, h.Body.Opcode)
			connError = conn.RespondError(h.ID, gokeyless.ErrUnexpectedOpcode)
			s.stats.logInvalid(requestBegin)
			continue
		default:
			connError = conn.RespondError(h.ID, gokeyless.ErrBadOpcode)
			s.stats.logInvalid(requestBegin)
			continue
		}

		if key, ok = s.Keys.Get(h.Body); !ok {
			log.Error(gokeyless.ErrKeyNotFound)
			connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
			s.stats.logInvalid(requestBegin)
			continue
		}

		// Ensure we don't perform an ECDSA sign for an RSA request.
		switch h.Body.Opcode {
		case gokeyless.OpRSASignMD5SHA1,
			gokeyless.OpRSASignSHA1,
			gokeyless.OpRSASignSHA224,
			gokeyless.OpRSASignSHA256,
			gokeyless.OpRSASignSHA384,
			gokeyless.OpRSASignSHA512:
			if _, ok := key.Public().(*rsa.PublicKey); !ok {
				log.Errorf("%s: request is RSA, but key isn't\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}
		}

		sig, err := key.Sign(rand.Reader, h.Body.Payload, opts)
		if err != nil {
			log.Errorf("%s: Signing error: %v\n", gokeyless.ErrCrypto, err)
			connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
			s.stats.logInvalid(requestBegin)
			continue
		}

		connError = conn.Respond(h.ID, sig)
		s.stats.logRequest(requestBegin)
	}

	if connError == io.EOF {
		log.Debug("connection closed by client")
	} else {
		log.Errorf("connection error: %v\n", connError)
	}
}
예제 #23
0
// NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte
// slices. key may be nil, and in this case NewRootCA will return a RootCA
// without a signer.
func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, error) {
	// Parse all the certificates in the cert bundle
	parsedCerts, err := helpers.ParseCertificatesPEM(certBytes)
	if err != nil {
		return RootCA{}, err
	}
	// Check to see if we have at least one valid cert
	if len(parsedCerts) < 1 {
		return RootCA{}, fmt.Errorf("no valid Root CA certificates found")
	}

	// Create a Pool with all of the certificates found
	pool := x509.NewCertPool()
	for _, cert := range parsedCerts {
		// Check to see if all of the certificates are valid, self-signed root CA certs
		if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
			return RootCA{}, fmt.Errorf("error while validating Root CA Certificate: %v", err)
		}
		pool.AddCert(cert)
	}

	// Calculate the digest for our Root CA bundle
	digest := digest.FromBytes(certBytes)

	if len(keyBytes) == 0 {
		// This RootCA does not have a valid signer.
		return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil
	}

	var (
		passphraseStr              string
		passphrase, passphrasePrev []byte
		priv                       crypto.Signer
	)

	// Attempt two distinct passphrases, so we can do a hitless passphrase rotation
	if passphraseStr = os.Getenv(PassphraseENVVar); passphraseStr != "" {
		passphrase = []byte(passphraseStr)
	}

	if p := os.Getenv(PassphraseENVVarPrev); p != "" {
		passphrasePrev = []byte(p)
	}

	// Attempt to decrypt the current private-key with the passphrases provided
	priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrase)
	if err != nil {
		priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrasePrev)
		if err != nil {
			log.Debug("Malformed private key %v", err)
			return RootCA{}, err
		}
	}

	// We will always use the first certificate inside of the root bundle as the active one
	if err := ensureCertKeyMatch(parsedCerts[0], priv.Public()); err != nil {
		return RootCA{}, err
	}

	signer, err := local.NewSigner(priv, parsedCerts[0], cfsigner.DefaultSigAlgo(priv), SigningPolicy(certExpiry))
	if err != nil {
		return RootCA{}, err
	}

	// If the key was loaded from disk unencrypted, but there is a passphrase set,
	// ensure it is encrypted, so it doesn't hit raft in plain-text
	keyBlock, _ := pem.Decode(keyBytes)
	if keyBlock == nil {
		// This RootCA does not have a valid signer.
		return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil
	}
	if passphraseStr != "" && !x509.IsEncryptedPEMBlock(keyBlock) {
		keyBytes, err = EncryptECPrivateKey(keyBytes, passphraseStr)
		if err != nil {
			return RootCA{}, err
		}
	}

	return RootCA{Signer: signer, Key: keyBytes, Digest: digest, Cert: certBytes, Pool: pool}, nil
}
예제 #24
0
파일: initca.go 프로젝트: bbandix/cfssl
// NewFromSigner creates a new root certificate from a crypto.Signer.
func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPEM []byte, err error) {

	var sigAlgo x509.SignatureAlgorithm
	switch pub := priv.Public().(type) {
	case *rsa.PublicKey:
		bitLength := pub.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.PublicKey:
		switch pub.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,
	}

	csrPEM, 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: csrPEM,
	}
	csrPEM = 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(csrPEM)}
	cert, err = s.Sign(signReq)
	return
}