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 }