aboutsummaryrefslogtreecommitdiff
path: root/client/keys.go
diff options
context:
space:
mode:
Diffstat (limited to 'client/keys.go')
-rw-r--r--client/keys.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/client/keys.go b/client/keys.go
new file mode 100644
index 0000000..4b3b69e
--- /dev/null
+++ b/client/keys.go
@@ -0,0 +1,84 @@
+package client
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+ "crypto/rsa"
+ "fmt"
+
+ "golang.org/x/crypto/ed25519"
+ "golang.org/x/crypto/ssh"
+)
+
+// Key is a private key.
+type Key interface{}
+type keyfunc func(int) (Key, ssh.PublicKey, error)
+
+var (
+ keytypes = map[string]keyfunc{
+ "rsa": generateRSAKey,
+ "ecdsa": generateECDSAKey,
+ "ed25519": generateED25519Key,
+ }
+)
+
+func generateED25519Key(bits int) (Key, ssh.PublicKey, error) {
+ p, k, err := ed25519.GenerateKey(rand.Reader)
+ if err != nil {
+ return nil, nil, err
+ }
+ pub, err := ssh.NewPublicKey(p)
+ if err != nil {
+ return nil, nil, err
+ }
+ return &k, pub, nil
+}
+
+func generateRSAKey(bits int) (Key, ssh.PublicKey, error) {
+ k, err := rsa.GenerateKey(rand.Reader, bits)
+ if err != nil {
+ return nil, nil, err
+ }
+ pub, err := ssh.NewPublicKey(&k.PublicKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ return k, pub, nil
+}
+
+func generateECDSAKey(bits int) (Key, ssh.PublicKey, error) {
+ var curve elliptic.Curve
+ switch bits {
+ case 256:
+ curve = elliptic.P256()
+ case 384:
+ curve = elliptic.P384()
+ case 521:
+ curve = elliptic.P521()
+ default:
+ return nil, nil, fmt.Errorf("Unsupported key size. Valid sizes are '256', '384', '521'")
+ }
+ k, err := ecdsa.GenerateKey(curve, rand.Reader)
+ if err != nil {
+ return nil, nil, err
+ }
+ pub, err := ssh.NewPublicKey(&k.PublicKey)
+ if err != nil {
+ return nil, nil, err
+ }
+ return k, pub, nil
+}
+
+// GenerateKey generates a ssh key-pair according to the type and size specified.
+func GenerateKey(keytype string, bits int) (Key, ssh.PublicKey, error) {
+ f, ok := keytypes[keytype]
+ if !ok {
+ var valid []string
+ for k := range keytypes {
+ valid = append(valid, k)
+ }
+ return nil, nil, fmt.Errorf("Unsupported key type %s. Valid choices are %s", keytype, valid)
+ }
+ return f(bits)
+}