From d4085cc29b9742a2e75c895d6551579eac4cea48 Mon Sep 17 00:00:00 2001 From: David Cowden <dcow@smallstep.com> Date: Thu, 27 Aug 2020 21:50:10 -0700 Subject: [PATCH] keys: add method to load cert and encrypted key Consumers can now have the convenience of loading an openssh style key and cert pair when the key is encrypted with a passphrase. --- keys.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/keys.go b/keys.go index 7353555..d483e90 100644 --- a/keys.go +++ b/keys.go @@ -19,6 +19,15 @@ func LoadCertFromKeyFileOpenSSH(keypath string) (ssh.Signer, error) { return LoadCertFromFiles(keypath, certpath) } +// LoadCertFromKeyFileEncOpenSSH returns an ssh.Signer from the encrypted key +// stored at the given filesystem path with a public key that is the ssh +// certificate loaded from the file "<path>-cert.pub". This is how ssh-add looks +// for certs when adding keys to ssh-agent. +func LoadCertFromKeyFileEncOpenSSH(keypath string, pass []byte) (ssh.Signer, error) { + certpath := keypath + "-cert.pub" + return LoadCertFromFilesEnc(keypath, certpath, pass) +} + // LoadCertFromFiles returns an ssh.Signer with private key loaded from the // unecrypted path keypath and a public cert component loaded from certpath. func LoadCertFromFiles(keypath, certpath string) (ssh.Signer, error) { @@ -44,6 +53,32 @@ func LoadCertFromFiles(keypath, certpath string) (ssh.Signer, error) { return signer, nil } +// LoadCertFromFilesEnc returns an ssh.Signer with private key loaded from the +// ecrypted key at path keypath and a public cert component loaded from certpath. +func LoadCertFromFilesEnc(keypath, certpath string, pass []byte) (ssh.Signer, error) { + // Read host key from a file, parse using x/crypto/ssh. + kb, err := ioutil.ReadFile(keypath) + if err != nil { + return nil, err + } + key, err := ssh.ParsePrivateKeyWithPassphrase(kb, pass) + if err != nil { + return nil, err + } + cb, err := ioutil.ReadFile(certpath) + if err != nil { + return nil, err + } + pub, _, _, _, err := ssh.ParseAuthorizedKey(cb) + if err != nil { + return nil, err + } + cert := pub.(*ssh.Certificate) + signer, err := ssh.NewCertSigner(cert, key) + return signer, nil +} + + // LoadKeyFromFile returns an ssh.Signer from the unencrypted key stored // at the given filesystem path. func LoadKeyFromFile(path string) (ssh.Signer, error) { -- GitLab