muun-recovery/libwallet/challenge_keys_test.go
2025-05-13 17:49:44 -03:00

161 lines
4.6 KiB
Go
Executable File

package libwallet
import (
"reflect"
"testing"
"github.com/btcsuite/btcutil/base58"
)
func TestNewChallengePrivateKey(t *testing.T) {
type args struct {
input []byte
salt []byte
}
tests := []struct {
name string
args args
want *ChallengePrivateKey
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewChallengePrivateKey(tt.args.input, tt.args.salt); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewChallengePrivateKey() = %v, want %v", got, tt.want)
}
})
}
}
func TestChallengeKeySignSha(t *testing.T) {
input := randomBytes(32)
salt := randomBytes(32)
challengePrivKey := NewChallengePrivateKey(input, salt)
payload := []byte("foobar")
_, err := challengePrivKey.SignSha(payload)
if err != nil {
t.Fatal(err)
}
// TODO(federicobond): assert that signature verifies
}
func TestChallengeKeyCrypto(t *testing.T) {
const birthday = 376
network := Regtest()
salt := randomBytes(8)
privKey, _ := NewHDPrivateKey(randomBytes(32), network)
challengePrivKey := NewChallengePrivateKey([]byte("a very good password"), salt)
encryptedKey, err := challengePrivKey.PubKey().EncryptKey(privKey, salt, birthday)
if err != nil {
t.Fatal(err)
}
decryptedKey, err := challengePrivKey.DecryptRawKey(encryptedKey, network)
if err != nil {
t.Fatal(err)
}
if privKey.String() != decryptedKey.Key.String() {
t.Fatalf("keys dont match: orig %v vs decrypted %v", privKey.String(), decryptedKey.Key.String())
}
if birthday != decryptedKey.Birthday {
t.Fatalf("birthdays dont match: expected %v got %v", birthday, decryptedKey.Birthday)
}
}
func TestChallengeKeyCryptoV2(t *testing.T) {
const (
encodedKey = "tprv8ZgxMBicQKsPcxg1GFGZgL5zALjPwijrYNUqTi2s9JsVqDLzbpX55U9JH2PKAQKExtpdTyboZmV2ytaqr9pAHuxE1hX8k9bQgZAjq25E6P7"
encryptedKey = "4LbSKwcepbbx4dPetoxvTWszb6mLyJHFhumzmdPRVprbn8XZBvFa6Ffarm6R3WGKutFzdxxJgQDdSHuYdjhDp1EZfSNbj12gXMND1AgmNijSxEua3LwVURU3nzWsvV5b1AsWEjJca24CaFY6T3C"
password = "a very good password"
saltLength = 8
birthday = 376
)
extractSalt := func(rawKey string) []byte {
bytes := base58.Decode(rawKey)
return bytes[len(bytes)-saltLength:]
}
challengeKey := NewChallengePrivateKey([]byte(password), extractSalt(encryptedKey))
decryptedKey, err := challengeKey.DecryptRawKey(encryptedKey, Regtest())
if err != nil {
t.Fatal(err)
}
if decryptedKey.Birthday != birthday {
t.Fatalf("decrypted birthday %v differs from expected %v", decryptedKey.Birthday, birthday)
}
if decryptedKey.Key.String() != encodedKey {
t.Fatalf("key doesnt match\ngot %v\nexpected %v\n", decryptedKey.Key.String(), encodedKey)
}
_, err = challengeKey.PubKey().EncryptKey(decryptedKey.Key, extractSalt(encryptedKey), birthday)
if err != nil {
t.Fatal(err)
}
}
func TestDecodeKeyWithOrWithoutSalt(t *testing.T) {
const (
// The same encoded key, with one version missing the salt field:
saltedKey = "4LbSKwcepbbx4dPetoxvTWszb6mLyJHFhumzmdPRVprbn8XZBvFa6Ffarm6R3WGKutFzdxxJgQDdSHuYdjhDp1EZfSNbj12gXMND1AgmNijSxEua3LwVURU3nzWsvV5b1AsWEjJca24CaFY6T3C"
unsaltedKey = "5XEEts6mc9WV34krDWsqmpLcPCw2JkK8qJu3gFdZpP8ngkERuQEsaDvYrGkhXUpM6jQRtimTYm4XnBPujpo3MsdYBedsNVxvT3WC6uCCFuzNUZCoydVY39yJXbxva7naDxH5iTra"
)
expected := &EncryptedPrivateKeyInfo{
Version: 2,
Birthday: 376,
CipherText: "f6af1ecd17052a81b75902c1712567cf1c650329875feb7e24af3e27235f384054ea549025e99dc2659f95bb6447cf861aa2ec0407ea74baf5a9d6a885ae184b",
EphPublicKey: "020a8d322dda8ff685d80b16681d4e87c109664cdc246a9d3625adfe0de203e71e",
Salt: "e3305526d0cd675f",
}
// Verify the salted version:
actual, err := DecodeEncryptedPrivateKey(saltedKey)
if err != nil {
t.Fatal(err)
}
assertDecodedKeysEqual(t, actual, expected)
// Verify the unsalted version:
actual, err = DecodeEncryptedPrivateKey(unsaltedKey)
if err != nil {
t.Fatal(err)
}
expected.Salt = "0000000000000000" // unsalted key should decode with zeroed field
assertDecodedKeysEqual(t, actual, expected)
}
func assertDecodedKeysEqual(t *testing.T, actual, expected *EncryptedPrivateKeyInfo) {
if actual.Version != expected.Version {
t.Fatalf("version %v expected %v", actual.Version, expected.Version)
}
if actual.Birthday != expected.Birthday {
t.Fatalf("birthday %v, expected %v", actual.Birthday, expected.Birthday)
}
if actual.CipherText != expected.CipherText {
t.Fatalf("cipherText %x expected %x", actual.CipherText, expected.CipherText)
}
if actual.EphPublicKey != expected.EphPublicKey {
t.Fatalf("ephPublicKey %x expected %x", actual.EphPublicKey, expected.EphPublicKey)
}
if actual.Salt != expected.Salt {
t.Fatalf("salt %x expected %x", actual.Salt, expected.Salt)
}
}