github.com/Finschia/finschia-sdk@v0.48.1/crypto/ledger/ledger_test.go (about)

     1  package ledger
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/Finschia/finschia-sdk/codec/legacy"
    10  	"github.com/Finschia/finschia-sdk/crypto/hd"
    11  	"github.com/Finschia/finschia-sdk/crypto/types"
    12  	"github.com/Finschia/finschia-sdk/testutil/testdata"
    13  	sdk "github.com/Finschia/finschia-sdk/types"
    14  )
    15  
    16  func TestErrorHandling(t *testing.T) {
    17  	// first, try to generate a key, must return an error
    18  	// (no panic)
    19  	path := *hd.NewParams(44, 555, 0, false, 0)
    20  	_, err := NewPrivKeySecp256k1Unsafe(path)
    21  	require.Error(t, err)
    22  }
    23  
    24  func TestPublicKeyUnsafe(t *testing.T) {
    25  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
    26  	priv, err := NewPrivKeySecp256k1Unsafe(path)
    27  	require.NoError(t, err)
    28  	checkDefaultPubKey(t, priv)
    29  }
    30  
    31  func checkDefaultPubKey(t *testing.T, priv types.LedgerPrivKey) {
    32  	require.NotNil(t, priv)
    33  	expectedPkStr := "PubKeySecp256k1{02BCD96CAB102304AC10E90C5A0F29358E3A4A6FB1217B83E5DB657918EA28BEC1}"
    34  	require.Equal(t, "eb5ae9872102bcd96cab102304ac10e90c5a0f29358e3a4a6fb1217b83e5db657918ea28bec1",
    35  		fmt.Sprintf("%x", cdc.Amino.MustMarshalBinaryBare(priv.PubKey())),
    36  		"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
    37  	require.Equal(t, expectedPkStr, priv.PubKey().String())
    38  	addr := sdk.AccAddress(priv.PubKey().Address()).String()
    39  	require.Equal(t, "link1tdl7n2acgmec0y5nng0q2fahl9khyct3cgsktn",
    40  		addr, "Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
    41  }
    42  
    43  func TestPublicKeyUnsafeHDPath(t *testing.T) {
    44  	expectedAnswers := []string{
    45  		"PubKeySecp256k1{02BCD96CAB102304AC10E90C5A0F29358E3A4A6FB1217B83E5DB657918EA28BEC1}",
    46  		"PubKeySecp256k1{025543C96E09392B9B7F416B47BE4520804ED064F9E342062DDE825E0554E24188}",
    47  		"PubKeySecp256k1{02B2DDE2CD78977664A3F3F231EB0B30818AB174D54FFE552205BED3B67DCD852C}",
    48  		"PubKeySecp256k1{020A64E4DF39E6CD90820A29758A80145EE4352B4BC3C1539184B52B58A9313CC1}",
    49  		"PubKeySecp256k1{031E5CA16AFBF9E576B77C176C0CD5B904F16B733668EA37DF16F624B64AD92D2F}",
    50  		"PubKeySecp256k1{026656F9797699F1C7D0217038378D523898257BF38511AB971655F4F775EAB510}",
    51  		"PubKeySecp256k1{027A0D54AC45A3FCB0702754EB08FDCE246336AF1B532B8F5D07FEDA03F4AA5B05}",
    52  		"PubKeySecp256k1{032B1121146F78E24C15710028E3465FCAEC6F0711D2B401923F8D07BDFFFB750D}",
    53  		"PubKeySecp256k1{03ED8BFEBE2B45E4A8F74267E6662B35ACBE1563029A1D8C52217AEF93893BB46F}",
    54  		"PubKeySecp256k1{02D70D97BDC48A1045CA51A5B86BE8208D7BB6431F64BADC424FDFBCFD292B8AD0}",
    55  	}
    56  
    57  	const numIters = 10
    58  
    59  	privKeys := make([]types.LedgerPrivKey, numIters)
    60  
    61  	// Check with device
    62  	for i := uint32(0); i < 10; i++ {
    63  		path := *hd.NewFundraiserParams(0, sdk.CoinType, i)
    64  		t.Logf("Checking keys at %v\n", path)
    65  
    66  		priv, err := NewPrivKeySecp256k1Unsafe(path)
    67  		require.NoError(t, err)
    68  		require.NotNil(t, priv)
    69  
    70  		// Check other methods
    71  		tmp := priv.(PrivKeyLedgerSecp256k1)
    72  		require.NoError(t, tmp.ValidateKey())
    73  		(&tmp).AssertIsPrivKeyInner()
    74  
    75  		// in this test we are chekcking if the generated keys are correct.
    76  		require.Equal(t, expectedAnswers[i], priv.PubKey().String(),
    77  			"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
    78  
    79  		// Store and restore
    80  		serializedPk := priv.Bytes()
    81  		require.NotNil(t, serializedPk)
    82  		require.True(t, len(serializedPk) >= 50)
    83  
    84  		privKeys[i] = priv
    85  	}
    86  
    87  	// Now check equality
    88  	for i := 0; i < 10; i++ {
    89  		for j := 0; j < 10; j++ {
    90  			require.Equal(t, i == j, privKeys[i].Equals(privKeys[j]))
    91  			require.Equal(t, i == j, privKeys[j].Equals(privKeys[i]))
    92  		}
    93  	}
    94  }
    95  
    96  func TestPublicKeySafe(t *testing.T) {
    97  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
    98  	priv, addr, err := NewPrivKeySecp256k1(path, "link")
    99  
   100  	require.NoError(t, err)
   101  	require.NotNil(t, priv)
   102  	require.Nil(t, ShowAddress(path, priv.PubKey(), sdk.GetConfig().GetBech32AccountAddrPrefix()))
   103  	checkDefaultPubKey(t, priv)
   104  
   105  	addr2 := sdk.AccAddress(priv.PubKey().Address()).String()
   106  	require.Equal(t, addr, addr2)
   107  }
   108  
   109  func TestPublicKeyHDPath(t *testing.T) {
   110  	expectedPubKeys := []string{
   111  		"PubKeySecp256k1{02BCD96CAB102304AC10E90C5A0F29358E3A4A6FB1217B83E5DB657918EA28BEC1}",
   112  		"PubKeySecp256k1{025543C96E09392B9B7F416B47BE4520804ED064F9E342062DDE825E0554E24188}",
   113  		"PubKeySecp256k1{02B2DDE2CD78977664A3F3F231EB0B30818AB174D54FFE552205BED3B67DCD852C}",
   114  		"PubKeySecp256k1{020A64E4DF39E6CD90820A29758A80145EE4352B4BC3C1539184B52B58A9313CC1}",
   115  		"PubKeySecp256k1{031E5CA16AFBF9E576B77C176C0CD5B904F16B733668EA37DF16F624B64AD92D2F}",
   116  		"PubKeySecp256k1{026656F9797699F1C7D0217038378D523898257BF38511AB971655F4F775EAB510}",
   117  		"PubKeySecp256k1{027A0D54AC45A3FCB0702754EB08FDCE246336AF1B532B8F5D07FEDA03F4AA5B05}",
   118  		"PubKeySecp256k1{032B1121146F78E24C15710028E3465FCAEC6F0711D2B401923F8D07BDFFFB750D}",
   119  		"PubKeySecp256k1{03ED8BFEBE2B45E4A8F74267E6662B35ACBE1563029A1D8C52217AEF93893BB46F}",
   120  		"PubKeySecp256k1{02D70D97BDC48A1045CA51A5B86BE8208D7BB6431F64BADC424FDFBCFD292B8AD0}",
   121  	}
   122  
   123  	expectedAddrs := []string{
   124  		"link1tdl7n2acgmec0y5nng0q2fahl9khyct3cgsktn",
   125  		"link1lzmehungm97jh0nme768v9wv28l8jr2dkkv357",
   126  		"link1p0yx9c9q4xsnedlcn24gqfry5dcu6e9xkhv9aj",
   127  		"link1cjjev0yzp90dxhsyxlxkwvrgl6vdw5p7qpxgfu",
   128  		"link1gf58l6wlscadkw2c9dpyd8se4hw37gu0zxx2g6",
   129  		"link1n93v9h6slh2e56lfu6vcy302f6ttxv5tt676ej",
   130  		"link124w2ltcv7wdhc85g07kta7yc4pwqk9qqsfq3c0",
   131  		"link17evhyfgwm70xjy8s3la64ek2x068aqezs24lth",
   132  		"link1clgcsmd9gcu4v9ec0qzqpr932aetwrqkxwswdh",
   133  		"link1hcttwju93d5m39467gjcq63p5kc4fdcn30dgd8",
   134  	}
   135  
   136  	const numIters = 10
   137  
   138  	privKeys := make([]types.LedgerPrivKey, numIters)
   139  
   140  	// Check with device
   141  	for i := 0; i < len(expectedAddrs); i++ {
   142  		path := *hd.NewFundraiserParams(0, sdk.CoinType, uint32(i))
   143  		t.Logf("Checking keys at %s\n", path)
   144  
   145  		priv, addr, err := NewPrivKeySecp256k1(path, "link")
   146  		require.NoError(t, err)
   147  		require.NotNil(t, addr)
   148  		require.NotNil(t, priv)
   149  
   150  		addr2 := sdk.AccAddress(priv.PubKey().Address()).String()
   151  		require.Equal(t, addr2, addr)
   152  		require.Equal(t,
   153  			expectedAddrs[i], addr,
   154  			"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
   155  
   156  		// Check other methods
   157  		tmp := priv.(PrivKeyLedgerSecp256k1)
   158  		require.NoError(t, tmp.ValidateKey())
   159  		(&tmp).AssertIsPrivKeyInner()
   160  
   161  		// in this test we are chekcking if the generated keys are correct and stored in a right path.
   162  		require.Equal(t,
   163  			expectedPubKeys[i], priv.PubKey().String(),
   164  			"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
   165  
   166  		// Store and restore
   167  		serializedPk := priv.Bytes()
   168  		require.NotNil(t, serializedPk)
   169  		require.True(t, len(serializedPk) >= 50)
   170  
   171  		privKeys[i] = priv
   172  	}
   173  
   174  	// Now check equality
   175  	for i := 0; i < 10; i++ {
   176  		for j := 0; j < 10; j++ {
   177  			require.Equal(t, i == j, privKeys[i].Equals(privKeys[j]))
   178  			require.Equal(t, i == j, privKeys[j].Equals(privKeys[i]))
   179  		}
   180  	}
   181  }
   182  
   183  func getFakeTx(accountNumber uint32) []byte {
   184  	tmp := fmt.Sprintf(
   185  		`{"account_number":"%d","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"5000"},"memo":"memo","msgs":[[""]],"sequence":"6"}`,
   186  		accountNumber)
   187  
   188  	return []byte(tmp)
   189  }
   190  
   191  func TestSignaturesHD(t *testing.T) {
   192  	for account := uint32(0); account < 100; account += 30 {
   193  		msg := getFakeTx(account)
   194  
   195  		path := *hd.NewFundraiserParams(account, sdk.CoinType, account/5)
   196  		t.Logf("Checking signature at %v    ---   PLEASE REVIEW AND ACCEPT IN THE DEVICE\n", path)
   197  
   198  		priv, err := NewPrivKeySecp256k1Unsafe(path)
   199  		require.NoError(t, err)
   200  
   201  		pub := priv.PubKey()
   202  		sig, err := priv.Sign(msg)
   203  		require.NoError(t, err)
   204  
   205  		valid := pub.VerifySignature(msg, sig)
   206  		require.True(t, valid, "Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
   207  	}
   208  }
   209  
   210  func TestRealDeviceSecp256k1(t *testing.T) {
   211  	msg := getFakeTx(50)
   212  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
   213  	priv, err := NewPrivKeySecp256k1Unsafe(path)
   214  	require.NoError(t, err)
   215  
   216  	pub := priv.PubKey()
   217  	sig, err := priv.Sign(msg)
   218  	require.NoError(t, err)
   219  
   220  	valid := pub.VerifySignature(msg, sig)
   221  	require.True(t, valid)
   222  
   223  	// now, let's serialize the public key and make sure it still works
   224  	bs := cdc.Amino.MustMarshalBinaryBare(priv.PubKey())
   225  	pub2, err := legacy.PubKeyFromBytes(bs)
   226  	require.Nil(t, err, "%+v", err)
   227  
   228  	// make sure we get the same pubkey when we load from disk
   229  	require.Equal(t, pub, pub2)
   230  
   231  	// signing with the loaded key should match the original pubkey
   232  	sig, err = priv.Sign(msg)
   233  	require.NoError(t, err)
   234  	valid = pub.VerifySignature(msg, sig)
   235  	require.True(t, valid)
   236  
   237  	// make sure pubkeys serialize properly as well
   238  	bs = legacy.Cdc.MustMarshal(pub)
   239  	bpub, err := legacy.PubKeyFromBytes(bs)
   240  	require.NoError(t, err)
   241  	require.Equal(t, pub, bpub)
   242  }