// ParsePrivateKeyPEM parses and returns a PEM-encoded private // key. The private key may be either an unencrypted PKCS#8, PKCS#1, // or elliptic private key. func ParsePrivateKeyPEM(keyPEM []byte) (key crypto.Signer, err error) { keyDER, err := GetKeyDERFromPEM(keyPEM) if err != nil { return nil, err } return derhelpers.ParsePrivateKeyDER(keyDER) }
// Take in either two or one safeBags and return the certificates and or // Private key within the bags func parseBags(bags []safeBag, password []byte) (certs []*x509.Certificate, key crypto.Signer, err error) { for _, bag := range bags { bagid := bag.ID.String() switch bagid { case certBagID: var CertBag certBag if _, err = asn1.Unmarshal(bag.Value.Bytes, &CertBag); err != nil { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err) } certs, err = x509.ParseCertificates(CertBag.Data) if err != nil { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err) } case pkcs8ShroudedBagID: var pkinfo encryptedPrivateKeyInfo if _, err := asn1.Unmarshal(bag.Value.Bytes, &pkinfo); err != nil { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err) } pkDecrypted, err := decrypt(pkinfo.AlgorithmIdentifier, pkinfo.EncryptedData, password) if err != nil { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err) } // Checking if private key data has been properly decoded var rv asn1.RawValue if _, err = asn1.Unmarshal(pkDecrypted, &rv); err != nil { return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err) } if key, err = derhelpers.ParsePrivateKeyDER(pkDecrypted); err != nil { return nil, nil, err } default: return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for certificate bags and PKCS #8 Shrouded Bags")) } } return certs, key, nil }
func parsePrivateKeySpec(spec string, cfg map[string]string) (crypto.Signer, error) { specURL, err := url.Parse(spec) if err != nil { return nil, err } var priv crypto.Signer switch specURL.Scheme { case "file": // A file spec will be parsed such that the root // directory of a relative path will be stored as the // hostname, and the remainder of the file's path is // stored in the Path field. log.Debug("loading private key file", specURL.Path) path := filepath.Join(specURL.Host, specURL.Path) in, err := ioutil.ReadFile(path) if err != nil { return nil, err } log.Debug("attempting to load PEM-encoded private key") priv, err = helpers.ParsePrivateKeyPEM(in) if err != nil { log.Debug("file is not a PEM-encoded private key") log.Debug("attempting to load DER-encoded private key") priv, err = derhelpers.ParsePrivateKeyDER(in) if err != nil { return nil, err } } log.Debug("loaded private key") return priv, nil case "rofile": log.Warning("Red October support is currently experimental") path := filepath.Join(specURL.Host, specURL.Path) in, err := ioutil.ReadFile(path) if err != nil { return nil, err } roServer := cfg["ro_server"] if roServer == "" { return nil, errors.New("config: no RedOctober server available") } // roCAPath can be empty; if it is, the client uses // the system default CA roots. roCAPath := cfg["ro_ca"] roUser := cfg["ro_user"] if roUser == "" { return nil, errors.New("config: no RedOctober user available") } roPass := cfg["ro_pass"] if roPass == "" { return nil, errors.New("config: no RedOctober passphrase available") } log.Debug("decrypting key via RedOctober Server") roClient, err := client.NewRemoteServer(roServer, roCAPath) if err != nil { return nil, err } req := core.DecryptRequest{ Name: roUser, Password: roPass, Data: in, } in, err = roClient.DecryptIntoData(req) if err != nil { return nil, err } return priv, nil default: return nil, ErrUnsupportedScheme } }