From c759c4772f0ca40a379cd19e63d3343b1e23714a Mon Sep 17 00:00:00 2001 From: Collin Williams <96917990+bluedragon1221@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:46:54 -0500 Subject: yokey: derived cryptography keys tool --- pkgs/yokey/main.go | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 pkgs/yokey/main.go (limited to 'pkgs/yokey/main.go') diff --git a/pkgs/yokey/main.go b/pkgs/yokey/main.go new file mode 100644 index 0000000..f5d0822 --- /dev/null +++ b/pkgs/yokey/main.go @@ -0,0 +1,146 @@ +package main + +import ( + "bufio" + "bytes" + "encoding/base64" + "encoding/hex" + "encoding/pem" + "fmt" + "io" + "os" + "strings" + + "golang.org/x/crypto/ssh" +) + +func readMasterKey() []byte { + reader := bufio.NewReader(os.Stdin) + input, err := reader.ReadString('\n') + if err != nil && err != io.EOF { + panic(err) + } + input = strings.TrimSpace(input) + if decoded, err := hex.DecodeString(input); err == nil { + return decoded + } + return []byte(input) +} + +func formatSignedMessage(message string, signature []byte) string { + var out bytes.Buffer + + out.WriteString("-----BEGIN SSH SIGNED MESSAGE-----\n") + out.WriteString(message) + if !strings.HasSuffix(message, "\n") { + out.WriteString("\n") + } + + sigBlock := pem.EncodeToMemory(&pem.Block{Type: "SSH SIGNATURE", Bytes: signature}) + out.Write(sigBlock) + + return out.String() +} + +func main() { + if len(os.Args) < 2 { + panic("usage: yokey ") + } + + mode := os.Args[1] + if mode == "gen" { + key := generateMasterKeyBytes() + fmt.Println(hex.EncodeToString(key)) + return + } + + if mode == "sshsig-public" { + master := readMasterKey() + signer := deriveSSHSigSigner(master) + fmt.Print(string(ssh.MarshalAuthorizedKey(signer.PublicKey()))) + return + } + + if mode == "sshsig-sign" { + if len(os.Args) != 4 { + panic("usage: yokey sshsig-sign ") + } + + namespace := os.Args[2] + message := []byte(os.Args[3]) + master := readMasterKey() + signature := signSSHSig(master, namespace, message) + fmt.Print(formatSignedMessage(string(message), signature)) + return + } + + if mode == "sshsig-verify" { + if len(os.Args) != 5 { + panic("usage: yokey sshsig-verify ") + } + + namespace := os.Args[2] + message := []byte(os.Args[3]) + signatureArg := strings.TrimSpace(os.Args[4]) + master := readMasterKey() + + signature, err := base64.StdEncoding.DecodeString(signatureArg) + if err != nil { + fmt.Println("invalid") + os.Exit(1) + } + + if err := verifySSHSig(master, namespace, message, signature); err != nil { + fmt.Println("invalid") + os.Exit(1) + } + + fmt.Println("ok") + return + } + + master := readMasterKey() + + if mode == "passwd" { + if len(os.Args) > 2 { + fmt.Println(derivePassword(master, os.Args[2])) + return + } else { + panic("must specify seed for password") + } + } + + var pub string + var priv string + + if mode == "ed25519" { + var privBytes []byte + if len(os.Args) > 3 { + pub, privBytes = deriveEd25519(master, os.Args[3]) + } else { + pub, privBytes = deriveEd25519(master, "") + } + priv = string(privBytes) + } + + if mode == "wg" { + if len(os.Args) > 3 { + pub, priv = deriveWireGuard(master, os.Args[3]) + } else { + pub, priv = deriveWireGuard(master, "") + } + } + + if len(os.Args) > 2 { + switch os.Args[2] { + case "public": + fmt.Print(pub) + return + case "private": + fmt.Print(priv) + return + } + } else { + panic("must specify mode for key: private or public") + } +} -- cgit v1.3.1