package cbk_test import ( "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "sneak.berlin/go/x/pkg/bip39wordlist" "sneak.berlin/go/x/pkg/cbk" ) // vectorRepeats is how many times "abandon" appears in the standard BIP39 // test vector for all-zero 128-bit entropy, which ends with "about". const vectorRepeats = bip39wordlist.MinWordCount - 1 // The keys below were pinned when the derivation was first implemented. // If this test starts failing, the derivation has changed and every key // anyone has derived with this package is no longer reproducible. const ( vectorPublicKeyHex = "db9c1ec248805579d0b0fe2d5a4814f96009f66a11c91260487b79167f881b20" vectorPrivateKeyHex = "eec3d5da4e348bd16df93b61c595bb5f75645f9aa468e72513be033a72b3d053" ) // vectorMnemonic returns the standard BIP39 test vector for all-zero // 128-bit entropy. func vectorMnemonic() string { return strings.Repeat("abandon ", vectorRepeats) + "about" } func TestNewMatchesPinnedVector(t *testing.T) { t.Parallel() keypair, err := cbk.FromMnemonic(vectorMnemonic()) require.NoError(t, err) assert.Equal(t, vectorPublicKeyHex, keypair.PublicKeyHex()) assert.Equal(t, vectorPrivateKeyHex, keypair.PrivateKeyHex()) } func TestNewNormalizesMnemonic(t *testing.T) { t.Parallel() canonical, err := cbk.FromMnemonic(vectorMnemonic()) require.NoError(t, err) messy, err := cbk.New(cbk.Params{ Mnemonic: " ABANDON\tAbandon " + strings.Repeat("abandon ", 9) + "\nabout\n", Passphrase: "", }) require.NoError(t, err) assert.Equal(t, canonical, messy) } func TestNewPassphraseChangesKeys(t *testing.T) { t.Parallel() plain, err := cbk.FromMnemonic(vectorMnemonic()) require.NoError(t, err) extraWord := "TREZOR" withExtraWord, err := cbk.New(cbk.Params{ Mnemonic: vectorMnemonic(), Passphrase: extraWord, }) require.NoError(t, err) assert.NotEqual(t, plain.PublicKey, withExtraWord.PublicKey) assert.NotEqual(t, plain.PrivateKey, withExtraWord.PrivateKey) again, err := cbk.New(cbk.Params{ Mnemonic: vectorMnemonic(), Passphrase: extraWord, }) require.NoError(t, err) assert.Equal(t, withExtraWord, again, "derivation is deterministic") } func TestNewDifferentMnemonicsGiveDifferentKeys(t *testing.T) { t.Parallel() first, err := bip39wordlist.GenerateMnemonic(bip39wordlist.MaxWordCount) require.NoError(t, err) second, err := bip39wordlist.GenerateMnemonic(bip39wordlist.MaxWordCount) require.NoError(t, err) firstKeypair, err := cbk.FromMnemonic(first) require.NoError(t, err) secondKeypair, err := cbk.FromMnemonic(second) require.NoError(t, err) assert.NotEqual(t, firstKeypair.PublicKey, secondKeypair.PublicKey) assert.NotEqual(t, firstKeypair.PrivateKey, secondKeypair.PrivateKey) } func TestNewRejectsInvalidMnemonic(t *testing.T) { t.Parallel() _, err := cbk.FromMnemonic("abandon bogus about") require.ErrorIs(t, err, bip39wordlist.ErrInvalidWordCount) _, err = cbk.FromMnemonic(strings.Repeat("abandon ", vectorRepeats) + "bogus") require.ErrorIs(t, err, bip39wordlist.ErrUnknownWord) } func TestKeyAccessors(t *testing.T) { t.Parallel() keypair, err := cbk.FromMnemonic(vectorMnemonic()) require.NoError(t, err) assert.Equal(t, keypair.PublicKey[:], keypair.PublicKeyBytes()) assert.Equal(t, keypair.PrivateKey[:], keypair.PrivateKeyBytes()) assert.Len(t, keypair.PublicKeyBytes(), cbk.KeySize) assert.Len(t, keypair.PrivateKeyBytes(), cbk.KeySize) assert.Equal(t, keypair.PublicKey.Hex(), keypair.PublicKeyHex()) assert.Equal(t, keypair.PrivateKey.Hex(), keypair.PrivateKeyHex()) assert.Len(t, keypair.PublicKeyHex(), 2*cbk.KeySize) }