Skeleton, mnemonic input, derivation, and the ssh pub and priv commands (closes #1)
All checks were successful
check / check (push) Successful in 5s

The module, the script entrypoints and Makefile, Docker-only linting, the mnemonic sources in the specified order with their refusals, the BIP-85 derivation, and keyfunc ssh pub and priv with the README test vectors as tests. Two review rounds; the second passed with no findings.

Model: opus-5 (implementation and review); fable-5-1 (landing)
This commit was merged in pull request #5.
This commit is contained in:
2026-09-07 17:34:54 +02:00
parent c3fd26a1de
commit 279cba6bcf
34 changed files with 1786 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
package sshkey_test
import (
"strings"
"testing"
"git.eeqj.de/sneak/keyfunc/internal/derive"
"git.eeqj.de/sneak/keyfunc/internal/sshkey"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
)
// example returns the mnemonic every BIP-39 document uses to show its
// test vectors: eleven abandons and about.
func example() string {
return strings.Repeat("abandon ", 11) + "about"
}
func TestTooFewBytesAreRefused(t *testing.T) {
t.Parallel()
_, err := sshkey.New([]byte("short"))
require.ErrorIs(t, err, sshkey.ErrSize)
}
func TestTheCommentIsPutAtTheEndOfTheLine(t *testing.T) {
t.Parallel()
key := forIndex(t, 0)
line, err := key.Line("hello")
require.NoError(t, err)
require.True(t, strings.HasPrefix(line, "ssh-ed25519 "))
require.True(t, strings.HasSuffix(line, " hello"))
}
func TestThePrivateKeyCarriesTheSamePublicKey(t *testing.T) {
t.Parallel()
key := forIndex(t, 0)
line, err := key.Line("")
require.NoError(t, err)
block, err := key.Block("a comment")
require.NoError(t, err)
parsed, err := ssh.ParsePrivateKey([]byte(block))
require.NoError(t, err)
back := strings.TrimSpace(
string(ssh.MarshalAuthorizedKey(parsed.PublicKey())),
)
require.Equal(t, line, back)
}
// forIndex derives the key for one index.
func forIndex(t *testing.T, index uint32) *sshkey.Key {
t.Helper()
material, err := derive.Bytes(example(), sshkey.Application, index)
require.NoError(t, err)
key, err := sshkey.New(material)
require.NoError(t, err)
return key
}