2019-11-28 17:09:18 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/x509"
|
|
|
|
"encoding/pem"
|
|
|
|
|
2019-11-28 22:52:35 +00:00
|
|
|
"github.com/pkg/errors"
|
2019-11-28 17:09:18 +00:00
|
|
|
"golang.org/x/crypto/ssh"
|
|
|
|
)
|
|
|
|
|
|
|
|
func signerFromPem(pemBytes []byte, password []byte) (ssh.Signer, error) {
|
2019-11-28 22:52:35 +00:00
|
|
|
var err error
|
2019-11-28 17:09:18 +00:00
|
|
|
|
|
|
|
// read pem block
|
|
|
|
pemBlock, _ := pem.Decode(pemBytes)
|
|
|
|
if pemBlock == nil {
|
2019-11-28 22:52:35 +00:00
|
|
|
return nil, errors.New("Pem decode failed, no key found")
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// handle encrypted key
|
|
|
|
if x509.IsEncryptedPEMBlock(pemBlock) {
|
|
|
|
// decrypt PEM
|
|
|
|
pemBlock.Bytes, err = x509.DecryptPEMBlock(pemBlock, password)
|
|
|
|
if err != nil {
|
2019-11-28 22:52:35 +00:00
|
|
|
return nil, errors.Wrap(err, "Decrypting PEM block failed")
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// get RSA, EC or DSA key
|
|
|
|
key, err := parsePemBlock(pemBlock)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// generate signer instance from key
|
|
|
|
signer, err := ssh.NewSignerFromKey(key)
|
|
|
|
if err != nil {
|
2019-11-28 22:52:35 +00:00
|
|
|
return nil, errors.Wrap(err, "Creating signer from encrypted key failed")
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return signer, nil
|
2019-11-28 22:52:35 +00:00
|
|
|
}
|
2019-11-28 17:09:18 +00:00
|
|
|
|
2019-11-28 22:52:35 +00:00
|
|
|
// generate signer instance from plain key
|
|
|
|
signer, err := ssh.ParsePrivateKey(pemBytes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Parsing plain private key failed")
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
2019-11-28 22:52:35 +00:00
|
|
|
|
|
|
|
return signer, nil
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func parsePemBlock(block *pem.Block) (interface{}, error) {
|
|
|
|
switch block.Type {
|
2019-11-28 22:52:35 +00:00
|
|
|
|
2019-11-28 17:09:18 +00:00
|
|
|
case "RSA PRIVATE KEY":
|
|
|
|
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
|
|
|
if err != nil {
|
2019-11-28 22:52:35 +00:00
|
|
|
return nil, errors.Wrap(err, "Parsing PKCS private key failed")
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
2019-11-28 22:52:35 +00:00
|
|
|
return key, nil
|
|
|
|
|
2019-11-28 17:09:18 +00:00
|
|
|
case "EC PRIVATE KEY":
|
|
|
|
key, err := x509.ParseECPrivateKey(block.Bytes)
|
|
|
|
if err != nil {
|
2019-11-28 22:52:35 +00:00
|
|
|
return nil, errors.Wrap(err, "Parsing EC private key failed")
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
2019-11-28 22:52:35 +00:00
|
|
|
return key, nil
|
|
|
|
|
2019-11-28 17:09:18 +00:00
|
|
|
case "DSA PRIVATE KEY":
|
|
|
|
key, err := ssh.ParseDSAPrivateKey(block.Bytes)
|
|
|
|
if err != nil {
|
2019-11-28 22:52:35 +00:00
|
|
|
return nil, errors.Wrap(err, "Parsing DSA private key failed")
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
2019-11-28 22:52:35 +00:00
|
|
|
return key, nil
|
|
|
|
|
2019-11-28 17:09:18 +00:00
|
|
|
default:
|
2019-11-28 22:52:35 +00:00
|
|
|
return nil, errors.Errorf("Parsing private key failed, unsupported key type %q", block.Type)
|
|
|
|
|
2019-11-28 17:09:18 +00:00
|
|
|
}
|
|
|
|
}
|