github.com/jerryclinesmith/packer@v0.3.7/communicator/ssh/keychain.go (about)

     1  package ssh
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/dsa"
     6  	"crypto/rsa"
     7  	"crypto/x509"
     8  	"encoding/pem"
     9  	"errors"
    10  	"io"
    11  )
    12  
    13  // SimpleKeychain makes it easy to use private keys in order to connect
    14  // via SSH, since the interface exposed by Go isn't the easiest to use
    15  // right away.
    16  type SimpleKeychain struct {
    17  	keys []interface{}
    18  }
    19  
    20  // AddPEMKey adds a simple PEM encoded private key to the keychain.
    21  func (k *SimpleKeychain) AddPEMKey(key string) (err error) {
    22  	block, _ := pem.Decode([]byte(key))
    23  	if block == nil {
    24  		return errors.New("no block in key")
    25  	}
    26  
    27  	var rsakey interface{}
    28  	rsakey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
    29  	if err != nil {
    30  		rsakey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
    31  	}
    32  
    33  	if err != nil {
    34  		return
    35  	}
    36  
    37  	k.keys = append(k.keys, rsakey)
    38  	return
    39  }
    40  
    41  // AddPEMKeyPassword adds a PEM encoded private key that is protected by
    42  // a password to the keychain.
    43  func (k *SimpleKeychain) AddPEMKeyPassword(key string, password string) (err error) {
    44  	block, _ := pem.Decode([]byte(key))
    45  	bytes, _ := x509.DecryptPEMBlock(block, []byte(password))
    46  	rsakey, err := x509.ParsePKCS1PrivateKey(bytes)
    47  	if err != nil {
    48  		return
    49  	}
    50  
    51  	k.keys = append(k.keys, rsakey)
    52  	return
    53  }
    54  
    55  // Key method for ssh.ClientKeyring interface
    56  func (k *SimpleKeychain) Key(i int) (interface{}, error) {
    57  	if i < 0 || i >= len(k.keys) {
    58  		return nil, nil
    59  	}
    60  	switch key := k.keys[i].(type) {
    61  	case *rsa.PrivateKey:
    62  		return &key.PublicKey, nil
    63  	case *dsa.PrivateKey:
    64  		return &key.PublicKey, nil
    65  	}
    66  	panic("unknown key type")
    67  }
    68  
    69  // Sign method for ssh.ClientKeyring interface
    70  func (k *SimpleKeychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
    71  	hashFunc := crypto.SHA1
    72  	h := hashFunc.New()
    73  	h.Write(data)
    74  	digest := h.Sum(nil)
    75  	switch key := k.keys[i].(type) {
    76  	case *rsa.PrivateKey:
    77  		return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
    78  	}
    79  	return nil, errors.New("ssh: unknown key type")
    80  }