From 321e26fae746e661d713cedfb6642609e680cafe Mon Sep 17 00:00:00 2001 From: fuero Date: Mon, 5 Jun 2017 23:28:13 +0200 Subject: Saving private keys (#61) * enables saving private keys * renames public_file_prefix to key_file_prefix and updates its docs to better reflect the changes --- vendor/github.com/mikesmitty/edkey/edkey.go | 88 +++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 vendor/github.com/mikesmitty/edkey/edkey.go (limited to 'vendor/github.com/mikesmitty/edkey/edkey.go') diff --git a/vendor/github.com/mikesmitty/edkey/edkey.go b/vendor/github.com/mikesmitty/edkey/edkey.go new file mode 100644 index 0000000..99aca55 --- /dev/null +++ b/vendor/github.com/mikesmitty/edkey/edkey.go @@ -0,0 +1,88 @@ +package edkey + +import ( + "math/rand" + + "golang.org/x/crypto/ed25519" + "golang.org/x/crypto/ssh" +) + +/* Writes ed25519 private keys into the new OpenSSH private key format. +I have no idea why this isn't implemented anywhere yet, you can do seemingly +everything except write it to disk in the OpenSSH private key format. */ +func MarshalED25519PrivateKey(key ed25519.PrivateKey) []byte { + // Add our key header (followed by a null byte) + magic := append([]byte("openssh-key-v1"), 0) + + var w struct { + CipherName string + KdfName string + KdfOpts string + NumKeys uint32 + PubKey []byte + PrivKeyBlock []byte + } + + // Fill out the private key fields + pk1 := struct { + Check1 uint32 + Check2 uint32 + Keytype string + Pub []byte + Priv []byte + Comment string + Pad []byte `ssh:"rest"` + }{} + + // Set our check ints + ci := rand.Uint32() + pk1.Check1 = ci + pk1.Check2 = ci + + // Set our key type + pk1.Keytype = ssh.KeyAlgoED25519 + + // Add the pubkey to the optionally-encrypted block + pk, ok := key.Public().(ed25519.PublicKey) + if !ok { + //fmt.Fprintln(os.Stderr, "ed25519.PublicKey type assertion failed on an ed25519 public key. This should never ever happen.") + return nil + } + pubKey := []byte(pk) + pk1.Pub = pubKey + + // Add our private key + pk1.Priv = []byte(key) + + // Might be useful to put something in here at some point + pk1.Comment = "" + + // Add some padding to match the encryption block size within PrivKeyBlock (without Pad field) + // 8 doesn't match the documentation, but that's what ssh-keygen uses for unencrypted keys. *shrug* + bs := 8 + blockLen := len(ssh.Marshal(pk1)) + padLen := (bs - (blockLen % bs)) % bs + pk1.Pad = make([]byte, padLen) + + // Padding is a sequence of bytes like: 1, 2, 3... + for i := 0; i < padLen; i++ { + pk1.Pad[i] = byte(i + 1) + } + + // Generate the pubkey prefix "\0\0\0\nssh-ed25519\0\0\0 " + prefix := []byte{0x0, 0x0, 0x0, 0x0b} + prefix = append(prefix, []byte(ssh.KeyAlgoED25519)...) + prefix = append(prefix, []byte{0x0, 0x0, 0x0, 0x20}...) + + // Only going to support unencrypted keys for now + w.CipherName = "none" + w.KdfName = "none" + w.KdfOpts = "" + w.NumKeys = 1 + w.PubKey = append(prefix, pubKey...) + w.PrivKeyBlock = ssh.Marshal(pk1) + + magic = append(magic, ssh.Marshal(w)...) + + return magic +} -- cgit v1.2.3