github.com/phobos182/packer@v0.2.3-0.20130819023704-c84d2aeffc68/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  	rsakey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    24  	if err != nil {
    25  		return
    26  	}
    27  
    28  	k.keys = append(k.keys, rsakey)
    29  	return
    30  }
    31  
    32  // AddPEMKeyPassword adds a PEM encoded private key that is protected by
    33  // a password to the keychain.
    34  func (k *SimpleKeychain) AddPEMKeyPassword(key string, password string) (err error) {
    35  	block, _ := pem.Decode([]byte(key))
    36  	bytes, _ := x509.DecryptPEMBlock(block, []byte(password))
    37  	rsakey, err := x509.ParsePKCS1PrivateKey(bytes)
    38  	if err != nil {
    39  		return
    40  	}
    41  
    42  	k.keys = append(k.keys, rsakey)
    43  	return
    44  }
    45  
    46  // Key method for ssh.ClientKeyring interface
    47  func (k *SimpleKeychain) Key(i int) (interface{}, error) {
    48  	if i < 0 || i >= len(k.keys) {
    49  		return nil, nil
    50  	}
    51  	switch key := k.keys[i].(type) {
    52  	case *rsa.PrivateKey:
    53  		return &key.PublicKey, nil
    54  	case *dsa.PrivateKey:
    55  		return &key.PublicKey, nil
    56  	}
    57  	panic("unknown key type")
    58  }
    59  
    60  // Sign method for ssh.ClientKeyring interface
    61  func (k *SimpleKeychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
    62  	hashFunc := crypto.SHA1
    63  	h := hashFunc.New()
    64  	h.Write(data)
    65  	digest := h.Sum(nil)
    66  	switch key := k.keys[i].(type) {
    67  	case *rsa.PrivateKey:
    68  		return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
    69  	}
    70  	return nil, errors.New("ssh: unknown key type")
    71  }