From f31f10e7229d76ef626aacb3c0600ad9f01b9d3e Mon Sep 17 00:00:00 2001
From: Nicolas Stalder <n@stalder.io>
Date: Mon, 18 May 2020 00:16:11 +0200
Subject: [PATCH] Support Ed25519 keys in setup

---
 main.go  | 5 ++++-
 setup.go | 9 +++++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/main.go b/main.go
index beafbfe..558f4b7 100644
--- a/main.go
+++ b/main.go
@@ -10,6 +10,7 @@ import (
 	"bytes"
 	"context"
 	"crypto/ecdsa"
+	"crypto/ed25519"
 	"crypto/rand"
 	"crypto/rsa"
 	"errors"
@@ -50,6 +51,7 @@ func main() {
 	}
 
 	socketPath := flag.String("l", "", "agent: path of the UNIX socket to listen on")
+	ed25519Flag := flag.Bool("ed25519", false, "setup: generate Ed25519 key")
 	resetFlag := flag.Bool("really-delete-all-piv-keys", false, "setup: reset the PIV applet")
 	setupFlag := flag.Bool("setup", false, "setup: configure a new YubiKey")
 	flag.Parse()
@@ -65,7 +67,7 @@ func main() {
 		if *resetFlag {
 			runReset(yk)
 		}
-		runSetup(yk)
+		runSetup(yk, *ed25519Flag)
 	} else {
 		if *socketPath == "" {
 			flag.Usage()
@@ -241,6 +243,7 @@ func getPublicKey(yk *piv.YubiKey, slot piv.Slot) (ssh.PublicKey, error) {
 	}
 	switch cert.PublicKey.(type) {
 	case *ecdsa.PublicKey:
+	case ed25519.PublicKey:
 	case *rsa.PublicKey:
 	default:
 		return nil, fmt.Errorf("unexpected public key type: %T", cert.PublicKey)
diff --git a/setup.go b/setup.go
index 7cba085..2b508fd 100644
--- a/setup.go
+++ b/setup.go
@@ -65,7 +65,7 @@ func runReset(yk *piv.YubiKey) {
 	}
 }
 
-func runSetup(yk *piv.YubiKey) {
+func runSetup(yk *piv.YubiKey, ed25519 bool) {
 	if _, err := yk.Certificate(piv.SlotAuthentication); err == nil {
 		log.Println("‼️  This YubiKey looks already setup")
 		log.Println("")
@@ -136,8 +136,13 @@ func runSetup(yk *piv.YubiKey) {
 		log.Fatalln("use --really-delete-all-piv-keys ⚠️")
 	}
 
+	alg := piv.AlgorithmEC256
+	if ed25519 {
+		// hack it in, this relies on the piv-go patch
+		alg = piv.AlgorithmEd25519
+	}
 	pub, err := yk.GenerateKey(key, piv.SlotAuthentication, piv.Key{
-		Algorithm:   piv.AlgorithmEC256,
+		Algorithm:   alg,
 		PINPolicy:   piv.PINPolicyOnce,
 		TouchPolicy: piv.TouchPolicyAlways,
 	})