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