From abcdd5a613ae77fb4cd39704ee152f87600920d9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 20 May 2013 22:50:13 -0700 Subject: [PATCH] communicator/ssh: Add SimpleKeychain --- communicator/ssh/keychain.go | 54 +++++++++++++++++++++++++++++++ communicator/ssh/keychain_test.go | 21 ++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 communicator/ssh/keychain.go create mode 100644 communicator/ssh/keychain_test.go diff --git a/communicator/ssh/keychain.go b/communicator/ssh/keychain.go new file mode 100644 index 000000000..8e409cf19 --- /dev/null +++ b/communicator/ssh/keychain.go @@ -0,0 +1,54 @@ +package ssh + +import ( + "crypto" + "crypto/dsa" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "io" +) + +type SimpleKeychain struct { + keys []interface{} +} + +// AddPEMKey adds a simple PEM encoded private key to the keychain. +func (k *SimpleKeychain) AddPEMKey(key string) (err error) { + block, _ := pem.Decode([]byte(key)) + rsakey, err := x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + return + } + + k.keys = append(k.keys, rsakey) + return +} + +// Key method for ssh.ClientKeyring interface +func (k *SimpleKeychain) Key(i int) (interface{}, error) { + if i < 0 || i >= len(k.keys) { + return nil, nil + } + switch key := k.keys[i].(type) { + case *rsa.PrivateKey: + return &key.PublicKey, nil + case *dsa.PrivateKey: + return &key.PublicKey, nil + } + panic("unknown key type") +} + +// Sign method for ssh.ClientKeyring interface +func (k *SimpleKeychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) { + hashFunc := crypto.SHA1 + h := hashFunc.New() + h.Write(data) + digest := h.Sum(nil) + switch key := k.keys[i].(type) { + case *rsa.PrivateKey: + return rsa.SignPKCS1v15(rand, key, hashFunc, digest) + } + return nil, errors.New("ssh: unknown key type") +} diff --git a/communicator/ssh/keychain_test.go b/communicator/ssh/keychain_test.go new file mode 100644 index 000000000..0cbc09fae --- /dev/null +++ b/communicator/ssh/keychain_test.go @@ -0,0 +1,21 @@ +package ssh + +import "testing" + +const testPrivateKey = `-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld +r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ +tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC +nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW +2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB +y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr +rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg== +-----END RSA PRIVATE KEY-----` + +func TestAddPEMKey(t *testing.T) { + k := &SimpleKeychain{} + err := k.AddPEMKey(testPrivateKey) + if err != nil { + t.Fatalf("error while adding key: %s", err) + } +}