// 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 } strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD") password := []byte(strPassword) if strPassword == "" { password = nil } priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password) if err != nil { log.Debug("Malformed private key %v", err) return nil, err } return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy) }
func NewCFSSLSigner(caFile, caKeyFile string) (*CFSSLSigner, error) { ca, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } cakey, err := ioutil.ReadFile(caKeyFile) if err != nil { return nil, err } parsedCa, err := helpers.ParseCertificatePEM(ca) if err != nil { return nil, err } strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD") password := []byte(strPassword) if strPassword == "" { password = nil } priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password) if err != nil { return nil, fmt.Errorf("Malformed private key %v", err) } return &CFSSLSigner{ priv: priv, ca: parsedCa, sigAlgo: signer.DefaultSigAlgo(priv), }, nil }
// NewCRLFromFile takes in a list of serial numbers, one per line, as well as the issuing certificate // of the CRL, and the private key. This function is then used to parse the list and generate a CRL func NewCRLFromFile(serialList, issuerFile, keyFile []byte, expiryTime string) ([]byte, error) { var revokedCerts []pkix.RevokedCertificate var oneWeek = time.Duration(604800) * time.Second expiryInt, err := strconv.ParseInt(expiryTime, 0, 32) if err != nil { return nil, err } newDurationFromInt := time.Duration(expiryInt) * time.Second newExpiryTime := time.Now().Add(newDurationFromInt) if expiryInt == 0 { newExpiryTime = time.Now().Add(oneWeek) } // Parse the PEM encoded certificate issuerCert, err := helpers.ParseCertificatePEM(issuerFile) if err != nil { return nil, err } // Split input file by new lines individualCerts := strings.Split(string(serialList), "\n") // For every new line, create a new revokedCertificate and add it to slice for _, value := range individualCerts { if len(strings.TrimSpace(value)) == 0 { continue } tempBigInt := new(big.Int) tempBigInt.SetString(value, 10) tempCert := pkix.RevokedCertificate{ SerialNumber: tempBigInt, RevocationTime: time.Now(), } revokedCerts = append(revokedCerts, tempCert) } strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD") password := []byte(strPassword) if strPassword == "" { password = nil } // Parse the key given key, err := helpers.ParsePrivateKeyPEMWithPassword(keyFile, password) if err != nil { log.Debug("Malformed private key %v", err) return nil, err } return CreateGenericCRL(revokedCerts, key, issuerCert, newExpiryTime) }
// 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 }
// 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 }