github.com/status-im/status-go@v1.1.0/server/pairing/payload_management_test.go (about)

     1  package pairing
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"crypto/sha256"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  	"github.com/stretchr/testify/suite"
    15  
    16  	"github.com/status-im/status-go/api"
    17  	"github.com/status-im/status-go/common/dbsetup"
    18  	"github.com/status-im/status-go/images"
    19  	"github.com/status-im/status-go/multiaccounts"
    20  	"github.com/status-im/status-go/protocol/requests"
    21  	"github.com/status-im/status-go/server/servertest"
    22  	"github.com/status-im/status-go/t/utils"
    23  )
    24  
    25  var (
    26  	password = "password"
    27  	keyUID   = "0x6b9a74f33316e02479c33ed23cf16e0408dca3e1b9ab8f361630859543eb0d46"
    28  	expected = multiaccounts.Account{
    29  		Name:          "cool account",
    30  		KeyUID:        keyUID,
    31  		ColorHash:     multiaccounts.ColorHash{{4, 3}, {4, 0}, {4, 3}, {4, 0}},
    32  		ColorID:       10,
    33  		Images:        images.SampleIdentityImages(),
    34  		KDFIterations: dbsetup.ReducedKDFIterationsNumber,
    35  	}
    36  	account1Hash = []byte{0x8f, 0xba, 0x35, 0x1, 0x2b, 0x9d, 0xad, 0xf0, 0x2d, 0x3c, 0x4d, 0x6, 0xb5, 0x22, 0x2, 0x47, 0xd4, 0x1c, 0xf4, 0x31, 0x2f, 0xb, 0x5b, 0x27, 0x5d, 0x43, 0x97, 0x58, 0x2d, 0xf0, 0xe1, 0xbe}
    37  	account2Hash = []byte{0x9, 0xf8, 0x5c, 0xe9, 0x92, 0x96, 0x2d, 0x88, 0x2b, 0x8e, 0x42, 0x3f, 0xa4, 0x93, 0x6c, 0xad, 0xe9, 0xc0, 0x1b, 0x8a, 0x8, 0x8c, 0x5e, 0x7a, 0x84, 0xa2, 0xf, 0x9f, 0x77, 0x58, 0x2c, 0x2c}
    38  )
    39  
    40  func TestPayloadMarshallerSuite(t *testing.T) {
    41  	suite.Run(t, new(PayloadMarshallerSuite))
    42  }
    43  
    44  type PayloadMarshallerSuite struct {
    45  	suite.Suite
    46  	servertest.TestLoggerComponents
    47  
    48  	teardown func()
    49  
    50  	config1 *SenderConfig
    51  	config2 *ReceiverConfig
    52  }
    53  
    54  func setupTestDB(t *testing.T) (*multiaccounts.Database, func()) {
    55  	tmpfile, err := ioutil.TempFile("", "accounts-tests-")
    56  	require.NoError(t, err)
    57  
    58  	db, err := multiaccounts.InitializeDB(tmpfile.Name())
    59  	require.NoError(t, err)
    60  
    61  	return db, func() {
    62  		require.NoError(t, db.Close())
    63  		require.NoError(t, os.Remove(tmpfile.Name()))
    64  	}
    65  }
    66  
    67  func makeKeystore(t *testing.T) string {
    68  	keyStoreDir := t.TempDir()
    69  	keyStoreDir = filepath.Join(keyStoreDir, api.DefaultKeystoreRelativePath)
    70  
    71  	err := os.MkdirAll(keyStoreDir, 0777)
    72  	require.NoError(t, err)
    73  
    74  	return keyStoreDir
    75  }
    76  
    77  func initKeys(t *testing.T, keyStoreDir string) {
    78  	utils.Init()
    79  	require.NoError(t, utils.ImportTestAccount(keyStoreDir, utils.GetAccount1PKFile()))
    80  	require.NoError(t, utils.ImportTestAccount(keyStoreDir, utils.GetAccount2PKFile()))
    81  }
    82  
    83  func getFiles(t *testing.T, keyStorePath string) map[string][]byte {
    84  	keys := make(map[string][]byte)
    85  
    86  	fileWalker := func(path string, fileInfo os.FileInfo, err error) error {
    87  		if err != nil {
    88  			return err
    89  		}
    90  		if fileInfo.IsDir() || filepath.Dir(path) != keyStorePath {
    91  			return nil
    92  		}
    93  
    94  		rawKeyFile, err := ioutil.ReadFile(path)
    95  		if err != nil {
    96  			return fmt.Errorf("invalid account key file: %v", err)
    97  		}
    98  
    99  		keys[fileInfo.Name()] = rawKeyFile
   100  		return nil
   101  	}
   102  
   103  	err := filepath.Walk(keyStorePath, fileWalker)
   104  	require.NoError(t, err)
   105  
   106  	return keys
   107  }
   108  
   109  func (pms *PayloadMarshallerSuite) SetupTest() {
   110  	pms.SetupLoggerComponents()
   111  
   112  	db1, db1td := setupTestDB(pms.T())
   113  	db2, db2td := setupTestDB(pms.T())
   114  	keystore1 := filepath.Join(makeKeystore(pms.T()), keyUID)
   115  	pms.teardown = func() {
   116  		db1td()
   117  		db2td()
   118  	}
   119  
   120  	initKeys(pms.T(), keystore1)
   121  	err := db1.SaveAccount(expected)
   122  	pms.Require().NoError(err)
   123  
   124  	pms.config1 = &SenderConfig{
   125  		DB:           db1,
   126  		KeystorePath: keystore1,
   127  		KeyUID:       keyUID,
   128  		Password:     password,
   129  	}
   130  
   131  	pms.config2 = &ReceiverConfig{
   132  		DB: db2,
   133  		CreateAccount: &requests.CreateAccount{
   134  			RootDataDir: pms.T().TempDir(),
   135  		},
   136  	}
   137  }
   138  
   139  func (pms *PayloadMarshallerSuite) TearDownTest() {
   140  	pms.teardown()
   141  }
   142  
   143  func (pms *PayloadMarshallerSuite) TestPayloadMarshaller_LoadPayloads() {
   144  	// Make a Payload
   145  	pp := new(AccountPayload)
   146  
   147  	// Make and Load() PairingPayloadRepository 1
   148  	ppr, err := NewAccountPayloadLoader(pp, pms.config1)
   149  	pms.Require().NoError(err)
   150  	err = ppr.Load()
   151  	pms.Require().NoError(err)
   152  
   153  	// TEST PairingPayloadRepository 1 Load()
   154  	pms.Require().Len(ppr.keys, 2)
   155  	pms.Require().Len(ppr.keys[utils.GetAccount1PKFile()], 489)
   156  	pms.Require().Len(ppr.keys[utils.GetAccount2PKFile()], 489)
   157  
   158  	h1 := sha256.New()
   159  	h1.Write(ppr.keys[utils.GetAccount1PKFile()])
   160  	pms.Require().Exactly(account1Hash, h1.Sum(nil))
   161  
   162  	h2 := sha256.New()
   163  	h2.Write(ppr.keys[utils.GetAccount2PKFile()])
   164  	pms.Require().Exactly(account2Hash, h2.Sum(nil))
   165  
   166  	pms.Require().Exactly(expected.ColorHash, ppr.multiaccount.ColorHash)
   167  	pms.Require().Exactly(expected.ColorID, ppr.multiaccount.ColorID)
   168  	pms.Require().Exactly(expected.Identicon, ppr.multiaccount.Identicon)
   169  	pms.Require().Exactly(expected.KeycardPairing, ppr.multiaccount.KeycardPairing)
   170  	pms.Require().Exactly(expected.KeyUID, ppr.multiaccount.KeyUID)
   171  	pms.Require().Exactly(expected.Name, ppr.multiaccount.Name)
   172  	pms.Require().Exactly(expected.Timestamp, ppr.multiaccount.Timestamp)
   173  	pms.Require().Len(ppr.multiaccount.Images, 2)
   174  	pms.Require().Equal(password, ppr.password)
   175  }
   176  
   177  func (pms *PayloadMarshallerSuite) TestPayloadMarshaller_MarshalToProtobuf() {
   178  	// Make a Payload
   179  	pp := new(AccountPayload)
   180  
   181  	// Make and Load() PairingPayloadRepository 1
   182  	ppr, err := NewAccountPayloadLoader(pp, pms.config1)
   183  	pms.Require().NoError(err)
   184  	err = ppr.Load()
   185  	pms.Require().NoError(err)
   186  
   187  	// Make and Load() PairingPayloadMarshaller 1
   188  	ppm := NewPairingPayloadMarshaller(pp, pms.Logger)
   189  
   190  	// TEST PairingPayloadMarshaller 1 MarshalProtobuf()
   191  	pb, err := ppm.MarshalProtobuf()
   192  	pms.Require().NoError(err)
   193  	pms.Require().Len(pb, 1384)
   194  
   195  	h := sha256.New()
   196  	h.Write(pb)
   197  	hashA := []byte{0xe5, 0x34, 0x2e, 0xf1, 0x81, 0x72, 0xab, 0xc3, 0xde, 0x54, 0xbc, 0x8e, 0xd8, 0x34, 0xbe, 0xab, 0xd, 0xe8, 0x84, 0x53, 0xa2, 0x14, 0x9b, 0xbe, 0xc5, 0xe5, 0xce, 0xa5, 0xe9, 0x6d, 0xbc, 0xdd}
   198  	hashB := []byte{0x98, 0x2b, 0x3d, 0x8b, 0x7c, 0x6a, 0x3e, 0xdc, 0x3, 0xb1, 0xbf, 0xf1, 0x50, 0x15, 0xa5, 0x0, 0xa8, 0xba, 0xae, 0xf9, 0x38, 0xa8, 0x65, 0xd8, 0xf0, 0x93, 0xca, 0xbc, 0x47, 0x5d, 0x84, 0x23}
   199  
   200  	// Because file-walk will pull files in an unpredictable order from a target dir
   201  	// there are 2 potential valid hashes, because there are 2 key files in the test dir
   202  	if !bytes.Equal(hashA, h.Sum(nil)) {
   203  		pms.Require().Exactly(hashB, h.Sum(nil))
   204  	}
   205  }
   206  
   207  func (pms *PayloadMarshallerSuite) TestPayloadMarshaller_UnmarshalProtobuf() {
   208  	// Make a Payload
   209  	pp := new(AccountPayload)
   210  
   211  	// Make and Load() PairingPayloadRepository 1
   212  	ppr, err := NewAccountPayloadLoader(pp, pms.config1)
   213  	pms.Require().NoError(err)
   214  	err = ppr.Load()
   215  	pms.Require().NoError(err)
   216  
   217  	// Make and Load() PairingPayloadMarshaller 1
   218  	ppm := NewPairingPayloadMarshaller(pp, pms.Logger)
   219  
   220  	pb, err := ppm.MarshalProtobuf()
   221  	pms.Require().NoError(err)
   222  
   223  	// Make a Payload
   224  	pp2 := new(AccountPayload)
   225  
   226  	// Make PairingPayloadMarshaller 2
   227  	ppm2 := NewPairingPayloadMarshaller(pp2, pms.Logger)
   228  
   229  	// TEST PairingPayloadMarshaller 2 is empty
   230  	pms.Require().Nil(ppm2.keys)
   231  	pms.Require().Nil(ppm2.multiaccount)
   232  	pms.Require().Empty(ppm2.password)
   233  
   234  	// TEST PairingPayloadMarshaller 2 UnmarshalProtobuf()
   235  	err = ppm2.UnmarshalProtobuf(pb)
   236  	pms.Require().NoError(err)
   237  
   238  	pms.Require().Len(ppm2.keys, 2)
   239  	pms.Require().Len(ppm2.keys[utils.GetAccount1PKFile()], 489)
   240  	pms.Require().Len(ppm2.keys[utils.GetAccount2PKFile()], 489)
   241  
   242  	h1 := sha256.New()
   243  	h1.Write(ppm2.keys[utils.GetAccount1PKFile()])
   244  	pms.Require().Exactly(account1Hash, h1.Sum(nil))
   245  
   246  	h2 := sha256.New()
   247  	h2.Write(ppm2.keys[utils.GetAccount2PKFile()])
   248  	pms.Require().Exactly(account2Hash, h2.Sum(nil))
   249  
   250  	pms.Require().Exactly(expected.ColorHash, ppm2.multiaccount.ColorHash)
   251  	pms.Require().Exactly(expected.ColorID, ppm2.multiaccount.ColorID)
   252  	pms.Require().Exactly(expected.Identicon, ppm2.multiaccount.Identicon)
   253  	pms.Require().Exactly(expected.KeycardPairing, ppm2.multiaccount.KeycardPairing)
   254  	pms.Require().Exactly(expected.KeyUID, ppm2.multiaccount.KeyUID)
   255  	pms.Require().Exactly(expected.Name, ppm2.multiaccount.Name)
   256  	pms.Require().Exactly(expected.Timestamp, ppm2.multiaccount.Timestamp)
   257  	pms.Require().Len(ppm2.multiaccount.Images, 2)
   258  	pms.Require().Equal(password, ppm2.password)
   259  }
   260  
   261  func (pms *PayloadMarshallerSuite) TestPayloadMarshaller_StorePayloads() {
   262  	// Make a Payload
   263  	pp := new(AccountPayload)
   264  
   265  	// Make and Load() PairingPayloadRepository 1
   266  	ppr, err := NewAccountPayloadLoader(pp, pms.config1)
   267  	pms.Require().NoError(err)
   268  	err = ppr.Load()
   269  	pms.Require().NoError(err)
   270  
   271  	// Make and Load() PairingPayloadMarshaller 1
   272  	ppm := NewPairingPayloadMarshaller(pp, pms.Logger)
   273  
   274  	pb, err := ppm.MarshalProtobuf()
   275  	pms.Require().NoError(err)
   276  
   277  	// Make a Payload
   278  	pp2 := new(AccountPayload)
   279  
   280  	// Make PairingPayloadMarshaller 2
   281  	ppm2 := NewPairingPayloadMarshaller(pp2, pms.Logger)
   282  
   283  	err = ppm2.UnmarshalProtobuf(pb)
   284  	pms.Require().NoError(err)
   285  
   286  	// Make and Load() PairingPayloadRepository 2
   287  	ppr2, err := NewAccountPayloadStorer(pp2, pms.config2)
   288  	require.NoError(pms.T(), err)
   289  	err = ppr2.Store()
   290  	pms.Require().NoError(err)
   291  
   292  	// TEST PairingPayloadRepository 2 Store()
   293  	keys := getFiles(pms.T(), filepath.Join(pms.config2.AbsoluteKeystorePath(), keyUID))
   294  
   295  	pms.Require().Len(keys, 2)
   296  	pms.Require().Len(keys[utils.GetAccount1PKFile()], 489)
   297  	pms.Require().Len(keys[utils.GetAccount2PKFile()], 489)
   298  
   299  	h1 := sha256.New()
   300  	h1.Write(keys[utils.GetAccount1PKFile()])
   301  	pms.Require().Exactly(account1Hash, h1.Sum(nil))
   302  
   303  	h2 := sha256.New()
   304  	h2.Write(keys[utils.GetAccount2PKFile()])
   305  	pms.Require().Exactly(account2Hash, h2.Sum(nil))
   306  
   307  	acc, err := pms.config2.DB.GetAccount(keyUID)
   308  	pms.Require().NoError(err)
   309  
   310  	pms.Require().Exactly(expected.ColorHash, acc.ColorHash)
   311  	pms.Require().Exactly(expected.ColorID, acc.ColorID)
   312  	pms.Require().Exactly(expected.Identicon, acc.Identicon)
   313  	pms.Require().Exactly(expected.KeycardPairing, acc.KeycardPairing)
   314  	pms.Require().Exactly(expected.KeyUID, acc.KeyUID)
   315  	pms.Require().Exactly(expected.Name, acc.Name)
   316  	pms.Require().Exactly(expected.Timestamp, acc.Timestamp)
   317  	pms.Require().Len(acc.Images, 2)
   318  
   319  	err = ppr2.storeKeys(ppr2.keystorePath)
   320  	pms.Require().ErrorIs(err, ErrKeyFileAlreadyExists)
   321  }
   322  
   323  func (pms *PayloadMarshallerSuite) TestPayloadMarshaller_LockPayload() {
   324  	AESKey := make([]byte, 32)
   325  	_, err := rand.Read(AESKey)
   326  	pms.Require().NoError(err)
   327  
   328  	pm := NewMockPayloadMounter(AESKey)
   329  
   330  	err = pm.Mount()
   331  	pms.Require().NoError(err)
   332  
   333  	toSend := pm.ToSend()
   334  	pms.Len(toSend, 60)
   335  
   336  	toSend2 := pm.ToSend()
   337  	pms.Len(toSend2, 60)
   338  
   339  	pm.LockPayload()
   340  
   341  	toSend3 := pm.ToSend()
   342  	pms.Nil(toSend3)
   343  }