// ParsePEMPrivateKey returns a data.PrivateKey from a PEM encoded private key. It // only supports RSA (PKCS#1) and attempts to decrypt using the passphrase, if encrypted. func ParsePEMPrivateKey(pemBytes []byte, passphrase string) (*data.PrivateKey, error) { block, _ := pem.Decode(pemBytes) if block == nil { return nil, errors.New("no valid private key found") } switch block.Type { case "RSA PRIVATE KEY": var privKeyBytes []byte var err error if x509.IsEncryptedPEMBlock(block) { privKeyBytes, err = x509.DecryptPEMBlock(block, []byte(passphrase)) if err != nil { return nil, errors.New("could not decrypt private key") } } else { privKeyBytes = block.Bytes } rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKeyBytes) if err != nil { return nil, fmt.Errorf("could not parse DER encoded key: %v", err) } tufRSAPrivateKey, err := RSAToPrivateKey(rsaPrivKey, data.RSAKey) if err != nil { return nil, fmt.Errorf("could not convert rsa.PrivateKey to data.PrivateKey: %v", err) } return tufRSAPrivateKey, nil case "EC PRIVATE KEY": var privKeyBytes []byte var err error if x509.IsEncryptedPEMBlock(block) { privKeyBytes, err = x509.DecryptPEMBlock(block, []byte(passphrase)) if err != nil { return nil, errors.New("could not decrypt private key") } } else { privKeyBytes = block.Bytes } ecdsaPrivKey, err := x509.ParseECPrivateKey(privKeyBytes) if err != nil { return nil, fmt.Errorf("could not parse DER encoded private key: %v", err) } tufECDSAPrivateKey, err := ECDSAToPrivateKey(ecdsaPrivKey, data.ECDSAKey) if err != nil { return nil, fmt.Errorf("could not convert ecdsa.PrivateKey to data.PrivateKey: %v", err) } return tufECDSAPrivateKey, nil default: return nil, fmt.Errorf("unsupported key type %q", block.Type) } }
// Read a PEM file and ask for a password to decrypt it if needed func ReadPEMData(pemFile string, pemPass []byte) ([]byte, error) { pemData, err := ioutil.ReadFile(pemFile) if err != nil { return pemData, err } // We should really just get the pem.Block back here, if there's other // junk on the end, warn about it. pemBlock, rest := pem.Decode(pemData) if len(rest) > 0 { log.Warning("Didn't parse all of", pemFile) } if x509.IsEncryptedPEMBlock(pemBlock) { // Decrypt and get the ASN.1 DER bytes here pemData, err = x509.DecryptPEMBlock(pemBlock, pemPass) if err != nil { return pemData, err } else { log.Info("Decrypted", pemFile, "successfully") } // Shove the decrypted DER bytes into a new pem Block with blank headers var newBlock pem.Block newBlock.Type = pemBlock.Type newBlock.Bytes = pemData // This is now like reading in an uncrypted key from a file and stuffing it // into a byte stream pemData = pem.EncodeToMemory(&newBlock) } return pemData, nil }
// PEMtoPublicKey unmarshals a pem to public key func PEMtoPublicKey(raw []byte, pwd []byte) (interface{}, error) { if len(raw) == 0 { return nil, errors.New("Invalid PEM. It must be diffrent from nil.") } block, _ := pem.Decode(raw) if block == nil { return nil, fmt.Errorf("Failed decoding. Block must be different from nil. [% x]", raw) } // TODO: derive from header the type of the key if x509.IsEncryptedPEMBlock(block) { if len(pwd) == 0 { return nil, errors.New("Encrypted Key. Password must be different from nil") } decrypted, err := x509.DecryptPEMBlock(block, pwd) if err != nil { return nil, fmt.Errorf("Failed PEM decryption. [%s]", err) } key, err := DERToPublicKey(decrypted) if err != nil { return nil, err } return key, err } cert, err := DERToPublicKey(block.Bytes) if err != nil { return nil, err } return cert, err }
// readKey returns the decrypted key pem bytes, and enforces the KEK if applicable // (writes it back with the correct encryption if it is not correctly encrypted) func (k *KeyReadWriter) readKey() (*pem.Block, error) { keyBlock, err := k.readKeyblock() if err != nil { return nil, err } if !x509.IsEncryptedPEMBlock(keyBlock) { return keyBlock, nil } // If it's encrypted, we can't read without a passphrase (we're assuming // empty passphrases iare invalid) if k.kekData.KEK == nil { return nil, ErrInvalidKEK{Wrapped: x509.IncorrectPasswordError} } derBytes, err := x509.DecryptPEMBlock(keyBlock, k.kekData.KEK) if err != nil { return nil, ErrInvalidKEK{Wrapped: err} } // remove encryption PEM headers headers := make(map[string]string) mergePEMHeaders(headers, keyBlock.Headers) return &pem.Block{ Type: keyBlock.Type, // the key type doesn't change Bytes: derBytes, Headers: headers, }, nil }
func addKeyAuth(auths []ssh.AuthMethod, keypath string) []ssh.AuthMethod { if len(keypath) == 0 { return auths } keypath = expandPath(keypath) // read the file pemBytes, err := ioutil.ReadFile(keypath) if err != nil { log.Print(err) os.Exit(1) } // get first pem block block, _ := pem.Decode(pemBytes) if block == nil { log.Printf("no key found in %s", keypath) return auths } // handle plain and encrypted keyfiles if x509.IsEncryptedPEMBlock(block) { log.Printf("warning: ignoring encrypted key '%s'", keypath) return auths } else { signer, err := ssh.ParsePrivateKey(pemBytes) if err != nil { log.Print(err) return auths } return append(auths, ssh.PublicKeys(signer)) } }
// PEMtoPublicKey unmarshals a pem to public key func PEMtoPublicKey(raw []byte, pwd []byte) (interface{}, error) { if len(raw) == 0 { return nil, utils.ErrNilArgument } block, _ := pem.Decode(raw) if block == nil { return nil, fmt.Errorf("Failed decoding [% x]", raw) } // TODO: derive from header the type of the key if x509.IsEncryptedPEMBlock(block) { if len(pwd) == 0 { return nil, errors.New("Encrypted Key. Need a password!!!") } decrypted, err := x509.DecryptPEMBlock(block, pwd) if err != nil { return nil, errors.New("Failed decryption!!!") } key, err := DERToPublicKey(decrypted) if err != nil { return nil, err } return key, err } cert, err := DERToPublicKey(block.Bytes) if err != nil { return nil, err } return cert, err }
// ReadPrivateKey attempts to read your private key and possibly decrypt it if it // requires a passphrase. // This function will prompt for a passphrase on STDIN if the environment variable (`IDENTITY_PASSPHRASE`), // is not set. func ReadPrivateKey(path string) ([]byte, error) { privateKey, err := ioutil.ReadFile(path) if err != nil { return nil, fmt.Errorf("failed to load identity: %v", err) } block, rest := pem.Decode(privateKey) if len(rest) > 0 { return nil, fmt.Errorf("extra data when decoding private key") } if !x509.IsEncryptedPEMBlock(block) { return privateKey, nil } passphrase := os.Getenv("IDENTITY_PASSPHRASE") if passphrase == "" { passphrase, err = gopass.GetPass("Enter passphrase: ") if err != nil { return nil, fmt.Errorf("couldn't read passphrase: %v", err) } } der, err := x509.DecryptPEMBlock(block, []byte(passphrase)) if err != nil { return nil, fmt.Errorf("decrypt failed: %v", err) } privateKey = pem.EncodeToMemory(&pem.Block{ Type: block.Type, Bytes: der, }) return privateKey, nil }
// PEMtoPublicKey unmarshals a pem to public key func PEMtoPublicKey(raw []byte, pwd []byte) (interface{}, error) { block, _ := pem.Decode(raw) // TODO: derive from header the type of the key if x509.IsEncryptedPEMBlock(block) { if pwd == nil { return nil, errors.New("Encrypted Key. Need a password!!!") } decrypted, err := x509.DecryptPEMBlock(block, pwd) if err != nil { return nil, errors.New("Failed decryption!!!") } key, err := DERToPublicKey(decrypted) if err != nil { return nil, err } return key, err } cert, err := DERToPublicKey(block.Bytes) if err != nil { return nil, err } return cert, err }
// SSHConfigPubKeyFile is a convience function that takes a username, private key // and passphrase and returns a new ssh.ClientConfig setup to pass credentials // to DialSSH func SSHConfigPubKeyFile(user string, file string, passphrase string) (*ssh.ClientConfig, error) { buf, err := ioutil.ReadFile(file) if err != nil { return nil, err } block, rest := pem.Decode(buf) if len(rest) > 0 { return nil, fmt.Errorf("pem: unable to decode file %s", file) } if x509.IsEncryptedPEMBlock(block) { b := block.Bytes b, err = x509.DecryptPEMBlock(block, []byte(passphrase)) if err != nil { return nil, err } buf = pem.EncodeToMemory(&pem.Block{ Type: block.Type, Bytes: b, }) } key, err := ssh.ParsePrivateKey(buf) if err != nil { return nil, err } return &ssh.ClientConfig{ User: user, Auth: []ssh.AuthMethod{ ssh.PublicKeys(key), }, }, nil }
// processPrivateKeyFile takes a private key file and an optional passphrase // and decodes it to a byte slice. func processPrivateKeyFile(privateKeyFile, passphrase string) ([]byte, error) { rawPrivateKeyBytes, err := ioutil.ReadFile(privateKeyFile) if err != nil { return nil, fmt.Errorf("Failed loading private key file: %s", err) } PEMBlock, _ := pem.Decode(rawPrivateKeyBytes) if PEMBlock == nil { return nil, fmt.Errorf( "%s does not contain a vaild private key", privateKeyFile) } if x509.IsEncryptedPEMBlock(PEMBlock) { if passphrase == "" { return nil, errors.New("a passphrase must be specified when using an encrypted private key") } decryptedPrivateKeyBytes, err := x509.DecryptPEMBlock(PEMBlock, []byte(passphrase)) if err != nil { return nil, fmt.Errorf("Failed decrypting private key: %s", err) } b := &pem.Block{ Type: "RSA PRIVATE KEY", Bytes: decryptedPrivateKeyBytes, } return pem.EncodeToMemory(b), nil } return rawPrivateKeyBytes, nil }
func server(config Config) { // open receive port readSocket := openUDPSocket(`r`, net.UDPAddr{ IP: net.IPv4(0, 0, 0, 0), Port: config.Port, }) fmt.Printf("Listening on UDP port %d...\n", config.Port) defer readSocket.Close() // main loop for { data := make([]byte, UDP_MSG_SIZE) size, clientAddr, err := readSocket.ReadFromUDP(data) if err != nil { fmt.Println("Error reading from receive port: ", err) } clientMsg := data[0:size] if string(clientMsg) == KEY_REQUEST_TEXT { fmt.Printf("Received key request from %s, sending key.\n", clientAddr.IP) // reply to the client on the same port writeSocket := openUDPSocket(`w`, net.UDPAddr{ IP: clientAddr.IP, Port: clientAddr.Port + 1, }) var keyData []byte keyData = []byte(os.Getenv(KEY_DATA_ENV_VAR)) if len(keyData) == 0 { keyData, err = ioutil.ReadFile(config.KeyPath) if err != nil { fmt.Printf("ERROR reading keyfile %s: %s!\n", config.KeyPath, err) } } pemBlock, _ := pem.Decode(keyData) if pemBlock != nil { if x509.IsEncryptedPEMBlock(pemBlock) { fmt.Println("Decrypting private key with passphrase...") decoded, err := x509.DecryptPEMBlock(pemBlock, []byte(config.Pwd)) if err == nil { header := `PRIVATE KEY` // default key type in header matcher := regexp.MustCompile("-----BEGIN (.*)-----") if matches := matcher.FindSubmatch(keyData); len(matches) > 1 { header = string(matches[1]) } keyData = pem.EncodeToMemory( &pem.Block{Type: header, Bytes: decoded}) } else { fmt.Printf("Error decrypting PEM-encoded secret: %s\n", err) } } } _, err = writeSocket.Write(keyData) if err != nil { fmt.Printf("ERROR writing data to socket:%s!\n", err) } writeSocket.Close() } } }
func readPEMFile(path, passphrase string) ([]byte, error) { pass := []byte(passphrase) var blocks []*pem.Block content, err := ioutil.ReadFile(path) if err != nil { return nil, err } for len(content) > 0 { var block *pem.Block block, content = pem.Decode(content) if block == nil { if len(blocks) == 0 { return nil, errors.New("no pem file") } break } if x509.IsEncryptedPEMBlock(block) { var buffer []byte var err error if len(pass) == 0 { err = errors.New("No passphrase available") } else { // Note, decrypting pem might succeed even with wrong password, but // only noise will be stored in buffer in this case. buffer, err = x509.DecryptPEMBlock(block, pass) } if err != nil { logp.Err("Dropping encrypted pem '%v' block read from %v. %v", block.Type, path, err) continue } // DEK-Info contains encryption info. Remove header to mark block as // unencrypted. delete(block.Headers, "DEK-Info") block.Bytes = buffer } blocks = append(blocks, block) } if len(blocks) == 0 { return nil, errors.New("no PEM blocks") } // re-encode available, decrypted blocks buffer := bytes.NewBuffer(nil) for _, block := range blocks { err := pem.Encode(buffer, block) if err != nil { return nil, err } } return buffer.Bytes(), nil }
// ParsePEMPrivateKey returns a data.PrivateKey from a PEM encoded private key. It // only supports RSA (PKCS#1) and attempts to decrypt using the passphrase, if encrypted. func ParsePEMPrivateKey(pemBytes []byte, passphrase string) (data.PrivateKey, error) { block, _ := pem.Decode(pemBytes) if block == nil { return nil, errors.New("no valid private key found") } var privKeyBytes []byte var err error if x509.IsEncryptedPEMBlock(block) { privKeyBytes, err = x509.DecryptPEMBlock(block, []byte(passphrase)) if err != nil { return nil, errors.New("could not decrypt private key") } } else { privKeyBytes = block.Bytes } switch block.Type { case "RSA PRIVATE KEY": rsaPrivKey, err := x509.ParsePKCS1PrivateKey(privKeyBytes) if err != nil { return nil, fmt.Errorf("could not parse DER encoded key: %v", err) } tufRSAPrivateKey, err := RSAToPrivateKey(rsaPrivKey) if err != nil { return nil, fmt.Errorf("could not convert rsa.PrivateKey to data.PrivateKey: %v", err) } return tufRSAPrivateKey, nil case "EC PRIVATE KEY": ecdsaPrivKey, err := x509.ParseECPrivateKey(privKeyBytes) if err != nil { return nil, fmt.Errorf("could not parse DER encoded private key: %v", err) } tufECDSAPrivateKey, err := ECDSAToPrivateKey(ecdsaPrivKey) if err != nil { return nil, fmt.Errorf("could not convert ecdsa.PrivateKey to data.PrivateKey: %v", err) } return tufECDSAPrivateKey, nil case "ED25519 PRIVATE KEY": // We serialize ED25519 keys by concatenating the private key // to the public key and encoding with PEM. See the // ED25519ToPrivateKey function. tufECDSAPrivateKey, err := ED25519ToPrivateKey(privKeyBytes) if err != nil { return nil, fmt.Errorf("could not convert ecdsa.PrivateKey to data.PrivateKey: %v", err) } return tufECDSAPrivateKey, nil default: return nil, fmt.Errorf("unsupported key type %q", block.Type) } }
func unencryptPrivateKey(block *pem.Block, password string) (crypto.PrivateKey, error) { if x509.IsEncryptedPEMBlock(block) { bytes, err := x509.DecryptPEMBlock(block, []byte(password)) if err != nil { return nil, ErrFailedToDecryptKey } return parsePrivateKey(bytes) } return parsePrivateKey(block.Bytes) }
// Determine if PEM file is encrypted func IsEncryptedPEM(pemFile string) bool { pemData, err := ioutil.ReadFile(pemFile) if err != nil { return false } pemBlock, _ := pem.Decode(pemData) if len(pemBlock.Bytes) == 0 { return false } return x509.IsEncryptedPEMBlock(pemBlock) }
func loadPrivateKey(path string) (ssh.AuthMethod, error) { // Read file keyData, err := ioutil.ReadFile(path) if err != nil { log.Printf("error: could not read key file '%s': %s", path, err) return nil, err } // Get first PEM block block, _ := pem.Decode(keyData) if err != nil { log.Printf("error: no key found in file '%s': %s", path, err) return nil, err } // If it's encrypted... var ( signer ssh.Signer signerErr error ) if x509.IsEncryptedPEMBlock(block) { // Get the passphrase prompt := fmt.Sprintf("Enter passphrase for key '%s': ", path) pass, err := speakeasy.Ask(prompt) if err != nil { log.Printf("error: error getting passphrase: %s", err) return nil, err } block.Bytes, err = x509.DecryptPEMBlock(block, []byte(pass)) if err != nil { log.Printf("error: error decrypting key: %s", err) return nil, err } key, err := ParsePEMBlock(block) if err != nil { log.Printf("error: could not parse PEM block: %s", err) return nil, err } signer, signerErr = ssh.NewSignerFromKey(key) } else { signer, signerErr = ssh.ParsePrivateKey(keyData) } if signerErr != nil { log.Printf("error: error parsing private key '%s': %s", path, signerErr) return nil, signerErr } return ssh.PublicKeys(signer), nil }
// checkRootKeyIsEncrypted makes sure the root key is encrypted. We have // internal assumptions that depend on this. func checkRootKeyIsEncrypted(pemBytes []byte) error { block, _ := pem.Decode(pemBytes) if block == nil { return ErrNoValidPrivateKey } if !x509.IsEncryptedPEMBlock(block) { return ErrRootKeyNotEncrypted } return nil }
func (a *SAuth) signInWithKey() (*signinResponse, error) { body := struct { PublicKey string `json:"publicKey"` Signature string `json:"signature"` }{} bytes, err := ioutil.ReadFile(a.Settings.PrivateKeyPath) if err != nil { return nil, err } block, _ := pem.Decode(bytes) if block == nil { return nil, errors.New("Private key is not PEM-encoded") } bytes = block.Bytes if x509.IsEncryptedPEMBlock(block) { passphrase := a.Prompts.KeyPassphrase(a.Settings.PrivateKeyPath) bytes, err = x509.DecryptPEMBlock(block, []byte(passphrase)) if err != nil { return nil, err } } privateKey, err := x509.ParsePKCS1PrivateKey(bytes) if err != nil { return nil, err } publicKey, err := ioutil.ReadFile(a.Settings.PrivateKeyPath + ".pub") if err != nil { return nil, err } body.PublicKey = string(publicKey) headers := httpclient.GetHeaders(a.Settings.SessionToken, a.Settings.Version, a.Settings.Pod, a.Settings.UsersID) message := fmt.Sprintf("%s&%s", headers["X-Request-Nonce"][0], headers["X-Request-Timestamp"][0]) hashedMessage := sha256.Sum256([]byte(message)) signature, err := privateKey.Sign(rand.Reader, hashedMessage[:], crypto.SHA256) if err != nil { return nil, err } body.Signature = base64.StdEncoding.EncodeToString(signature) b, err := json.Marshal(body) if err != nil { return nil, err } resp, statusCode, err := httpclient.Post(b, fmt.Sprintf("%s%s/auth/signin/key", a.Settings.AuthHost, a.Settings.AuthHostVersion), headers) if err != nil { return nil, err } signinResp := &signinResponse{} return signinResp, httpclient.ConvertResp(resp, statusCode, signinResp) }
func parseKey(block *pem.Block, passphrase []byte) (*rsa.PrivateKey, error) { var blockBytes []byte if x509.IsEncryptedPEMBlock(block) { b, err := x509.DecryptPEMBlock(block, passphrase) if err != nil { return nil, err } blockBytes = b } else { blockBytes = block.Bytes } return x509.ParsePKCS1PrivateKey(blockBytes) }
func addKeyAuth(auths []ssh.AuthMethod, keypath string) []ssh.AuthMethod { if len(keypath) == 0 { return auths } // read the file pemBytes, err := ioutil.ReadFile(keypath) if err != nil { log.Print(err) os.Exit(1) } // get first pem block block, _ := pem.Decode(pemBytes) if block == nil { log.Printf("no key found in %s", keypath) return auths } // handle plain and encrypted keyfiles if x509.IsEncryptedPEMBlock(block) { prompt := fmt.Sprintf("Enter passphrase for key '%s': ", keypath) pass, err := getpass(prompt) if err != nil { return auths } block.Bytes, err = x509.DecryptPEMBlock(block, []byte(pass)) if err != nil { log.Print(err) return auths } key, err := ParsePemBlock(block) if err != nil { log.Print(err) return auths } signer, err := ssh.NewSignerFromKey(key) if err != nil { log.Print(err) return auths } return append(auths, ssh.PublicKeys(signer)) } else { signer, err := ssh.ParsePrivateKey(pemBytes) if err != nil { log.Print(err) return auths } return append(auths, ssh.PublicKeys(signer)) } }
func (c *SSHCluster) findSSHKeySigners() (signers []privateKeySigner) { keyDir := filepath.Join(c.sshDir()) if stat, err := os.Stat(keyDir); err != nil || !stat.IsDir() { return } walkFunc := func(path string, info os.FileInfo, err error) error { if info.IsDir() { return nil } if strings.HasSuffix(path, ".pub") { return nil } data, err := ioutil.ReadFile(path) if err != nil { return nil } b, _ := pem.Decode(data) if b == nil { return nil } s := privateKeySigner{ base: c.base, path: path, pem: b, Encrypted: x509.IsEncryptedPEMBlock(b), } if s.Encrypted { publicKeyPath := fmt.Sprintf("%s.pub", path) if stat, err := os.Stat(publicKeyPath); err == nil && !stat.IsDir() { if data, err := ioutil.ReadFile(publicKeyPath); err == nil { pk, _, _, _, err := ssh.ParseAuthorizedKey(data) if err == nil { s.publicKey = pk } } } signers = append(signers, s) return nil } privateKey, err := x509.ParsePKCS1PrivateKey(b.Bytes) if err != nil { return nil } s.key = privateKey signers = append(signers, s) return nil } filepath.Walk(keyDir, walkFunc) sort.Sort(decryptedFirst(signers)) return }
func DecryptPemBlock(block *pem.Block, prompt func() (string, error)) (err error) { if x509.IsEncryptedPEMBlock(block) { if password, err := prompt(); nil != err { return err } else if data, err := x509.DecryptPEMBlock(block, []byte(password)); nil != err { return err } else { delete(block.Headers, "Proc-Type") delete(block.Headers, "DEK-Info") block.Bytes = data } } return nil }
func (c *Connection) newCertificate() (*tls.Certificate, error) { var certPEMBlock *pem.Block var keyPEMBlock *pem.Block var rest []byte rest = c.certificate for { certPEMBlock, rest = pem.Decode(rest) if certPEMBlock == nil || certPEMBlock.Type == "CERTIFICATE" { break } } if certPEMBlock == nil { return nil, errors.New("Failed to parse certificate data") } rest = c.certificate for { keyPEMBlock, rest = pem.Decode(rest) if keyPEMBlock == nil || keyPEMBlock.Type == "RSA PRIVATE KEY" { break } } if keyPEMBlock == nil { return nil, errors.New("Failed to parse key data") } if x509.IsEncryptedPEMBlock(keyPEMBlock) { der, err := x509.DecryptPEMBlock(keyPEMBlock, c.passphrase) if err != nil { return nil, errors.New("Failed to decrypt: wrong passphrase") } keyPEMBlock = &pem.Block{ Type: keyPEMBlock.Type, Headers: keyPEMBlock.Headers, Bytes: der, } } certBytes := pem.EncodeToMemory(certPEMBlock) keyBytes := pem.EncodeToMemory(keyPEMBlock) cert, err := tls.X509KeyPair(certBytes, keyBytes) return &cert, err }
// SetRSA reads PEM byte data and decodes it and parses the private key. // Applies the private and the public key to the AuthManager. Password as second // argument is only required when the private key is encrypted. // Checks for io.Close and closes the resource. Public key will be derived from // the private key. Default Signing bits 256. func SetRSA(privateKey io.Reader, password ...[]byte) OptionFunc { if cl, ok := privateKey.(io.Closer); ok { defer func() { if err := cl.Close(); err != nil { // close file log.Error("userjwt.RSAKey.ioCloser", "err", err) } }() } prKeyData, errRA := ioutil.ReadAll(privateKey) if errRA != nil { return func(a *AuthManager) { a.lastError = errgo.Mask(errRA) } } var prKeyPEM *pem.Block if prKeyPEM, _ = pem.Decode(prKeyData); prKeyPEM == nil { return func(a *AuthManager) { a.lastError = errgo.New("Private Key from io.Reader no found") } } var rsaPrivateKey *rsa.PrivateKey var err error if x509.IsEncryptedPEMBlock(prKeyPEM) { if len(password) != 1 || len(password[0]) == 0 { return func(a *AuthManager) { a.lastError = errgo.New("Private Key is encrypted but password was not set") } } var dd []byte var errPEM error if dd, errPEM = x509.DecryptPEMBlock(prKeyPEM, password[0]); errPEM != nil { return func(a *AuthManager) { a.lastError = errgo.Newf("Private Key decryption failed: %s", errPEM.Error()) } } rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(dd) } else { rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(prKeyPEM.Bytes) } return func(a *AuthManager) { a.SigningMethod = jwt.SigningMethodRS256 a.rsapk = rsaPrivateKey a.hasKey = true a.lastError = errgo.Mask(err) } }
func loadSigningKey() (*rsa.PrivateKey, error) { // Verify that we have a key path. if *keyPath == "" { return nil, fmt.Errorf("missing required parameter: key-path") } // Read the key file. pemData, err := ioutil.ReadFile(*keyPath) if err != nil { return nil, fmt.Errorf("unable to read private key file: %s", err) } // Extract the PEM-encoded data block. block, _ := pem.Decode(pemData) if block == nil { return nil, fmt.Errorf("bad private key data: not PEM-encoded") } if got, want := block.Type, "RSA PRIVATE KEY"; got != want { return nil, fmt.Errorf("unknown key type %q: expected %q", got, want) } // Get the key bytes. keyBytes := []byte(nil) if x509.IsEncryptedPEMBlock(block) { // We need the password if the key is encrypted. if *keyPassword == "" { return nil, fmt.Errorf("no password provided for private key") } // Decrypt the data block. keyBytes, err = x509.DecryptPEMBlock(block, []byte(*keyPassword)) if err != nil { return nil, fmt.Errorf("unable to decrypt private key: %s", err) } } else { keyBytes = block.Bytes } // Decode the private key. privateKey, err := x509.ParsePKCS1PrivateKey(keyBytes) if err != nil { return nil, fmt.Errorf("bad private key: %s", err) } return privateKey, nil }
// PEMtoAES extracts from the PEM an AES key func PEMtoAES(raw []byte, pwd []byte) ([]byte, error) { block, _ := pem.Decode(raw) if x509.IsEncryptedPEMBlock(block) { if pwd == nil { return nil, errors.New("Encrypted Key. Need a password!!!") } decrypted, err := x509.DecryptPEMBlock(block, pwd) if err != nil { return nil, err } return decrypted, nil } return block.Bytes, nil }
func loadAndDecryptKey(filename string) (*pem.Block, error) { f, err := os.Open(filename) if err != nil { return nil, err } defer f.Close() data, err := ioutil.ReadAll(f) if err != nil { return nil, err } block, _ := pem.Decode(data) if block == nil { return nil, err } if x509.IsEncryptedPEMBlock(block) { var passphrase string var decryptedBytes []byte for i := 0; i < 3; i++ { passphrase, err = ask.HiddenAsk("Passphrase: ") if err != nil { return nil, err } decryptedBytes, err = x509.DecryptPEMBlock(block, []byte(passphrase)) if err == nil { break } if err != x509.IncorrectPasswordError { return nil, err } } if err != nil { return nil, err } return &pem.Block{ Type: block.Type, Bytes: decryptedBytes, }, nil } return block, nil }
func (c *SSHCluster) importSSHKeyPair(t *TargetServer) error { var buf bytes.Buffer _, file, readFileErrChan := c.base.PromptFileInput(fmt.Sprintf("Please provide your private key for %s@%s", t.User, t.IP)) if _, err := io.Copy(&buf, file); err != nil { readFileErrChan <- err return err } readFileErrChan <- nil // no error reading file b, _ := pem.Decode(buf.Bytes()) if b == nil { return fmt.Errorf("Invalid private key") } var pemBytes []byte if x509.IsEncryptedPEMBlock(b) { passphrase := c.base.PromptProtectedInput("Please enter the passphrase for the key") var err error pemBytes, err = x509.DecryptPEMBlock(b, []byte(passphrase)) if err != nil { return err } } else { pemBytes = b.Bytes } privateKey, err := x509.ParsePKCS1PrivateKey(pemBytes) if err != nil { return err } signer, err := ssh.NewSignerFromKey(privateKey) if err != nil { return err } auth := []ssh.AuthMethod{ssh.PublicKeys(signer)} sshConfig := c.sshConfigForAuth(t, auth) c.base.SendLog(fmt.Sprintf("Testing provided key for %s@%s", t.User, t.IP)) if !c.testAndAddAuthentication(t, sshConfig) { return fmt.Errorf("Provided key for %s@%s failed to authenticate", t.User, t.IP) } c.base.SendLog(fmt.Sprintf("Key verified for %s@%s", t.User, t.IP)) return nil }
// LoadPKCS1PrivateKeyPEM load & parse private key from PEM-file func LoadPKCS1PrivateKeyPEM(path, password string) (*rsa.PrivateKey, error) { bytes, err := ioutil.ReadFile(path) if err != nil { return nil, err } block, _ := pem.Decode(bytes) if block == nil { return nil, errors.New("Invalid key; no PEM data found") } if block.Type != "RSA PRIVATE KEY" { return nil, errors.New("Invalid key; no RSA PRIVATE KEY block") } var data []byte if !x509.IsEncryptedPEMBlock(block) { data = block.Bytes } else if data, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil { return nil, err } return x509.ParsePKCS1PrivateKey(data) }
// https://github.com/rapidloop/rtop/blob/ba5b35e964135d50e0babedf0bd69b2fcb5dbcb4/src/sshhelper.go#L100 func addKeyAuth(auths []ssh.AuthMethod, keypath string, keypassword string) ([]ssh.AuthMethod, error) { if len(keypath) == 0 { return auths, nil } // read the file pemBytes, err := ioutil.ReadFile(keypath) if err != nil { return auths, err } // get first pem block block, _ := pem.Decode(pemBytes) if block == nil { return auths, fmt.Errorf("no key found in %s", keypath) } // handle plain and encrypted keyfiles if x509.IsEncryptedPEMBlock(block) { block.Bytes, err = x509.DecryptPEMBlock(block, []byte(keypassword)) if err != nil { return auths, err } key, err := parsePemBlock(block) if err != nil { return auths, err } signer, err := ssh.NewSignerFromKey(key) if err != nil { return auths, err } return append(auths, ssh.PublicKeys(signer)), nil } signer, err := ssh.ParsePrivateKey(pemBytes) if err != nil { return auths, err } return append(auths, ssh.PublicKeys(signer)), nil }