From 0b6ad662b519ce0bc0f0c1c65f8c5eb77ddb2904 Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Fri, 7 Feb 2020 12:56:30 +0100 Subject: [PATCH] Bug/validate pubkey (#1838) * validate chat before persisting * add comment to public key generation --- VERSION | 2 +- protocol/chat.go | 17 +++++ protocol/chat_test.go | 72 +++++++++++++++++++ protocol/identity/alias/generate.go | 1 + protocol/messenger.go | 5 ++ protocol/messenger_test.go | 1 + protocol/persistence.go | 4 ++ .../status-im/status-go/protocol/chat.go | 17 +++++ .../protocol/identity/alias/generate.go | 1 + .../status-im/status-go/protocol/messenger.go | 5 ++ .../status-go/protocol/persistence.go | 4 ++ 11 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 protocol/chat_test.go diff --git a/VERSION b/VERSION index 8298bb08b..f8287cf95 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.43.0 +0.43.1 diff --git a/protocol/chat.go b/protocol/chat.go index e6372fdca..c49e27a8c 100644 --- a/protocol/chat.go +++ b/protocol/chat.go @@ -5,6 +5,7 @@ import ( "crypto/sha1" "encoding/hex" "encoding/json" + "errors" "math/rand" "github.com/status-im/status-go/eth-node/crypto" @@ -79,6 +80,22 @@ func (c *Chat) Public() bool { return c.ChatType == ChatTypePublic } +func (c *Chat) OneToOne() bool { + return c.ChatType == ChatTypeOneToOne +} + +func (c *Chat) Validate() error { + if c.ID == "" { + return errors.New("chatID can't be blank") + } + + if c.OneToOne() { + _, err := c.PublicKey() + return err + } + return nil +} + func (c *Chat) MarshalJSON() ([]byte, error) { type ChatAlias Chat item := struct { diff --git a/protocol/chat_test.go b/protocol/chat_test.go new file mode 100644 index 000000000..45b1ca382 --- /dev/null +++ b/protocol/chat_test.go @@ -0,0 +1,72 @@ +package protocol + +import ( + "testing" + + "github.com/stretchr/testify/suite" +) + +type ChatTestSuite struct { + suite.Suite +} + +func TestChatSuite(t *testing.T) { + suite.Run(t, new(ChatTestSuite)) +} + +func (s *ChatTestSuite) TestValidateChat() { + testCases := []struct { + Name string + Valid bool + Chat Chat + }{ + { + Name: "valid one to one chat", + Valid: true, + Chat: Chat{ + ID: "0x0424a68f89ba5fcd5e0640c1e1f591d561fa4125ca4e2a43592bc4123eca10ce064e522c254bb83079ba404327f6eafc01ec90a1444331fe769d3f3a7f90b0dde1", + Name: "", + ChatType: ChatTypeOneToOne, + }, + }, + { + Name: "valid public chat", + Valid: true, + Chat: Chat{ + ID: "status", + Name: "status", + ChatType: ChatTypePublic, + }, + }, + { + Name: "empty chatID", + Valid: false, + Chat: Chat{ + ID: "", + Name: "status", + ChatType: ChatTypePublic, + }, + }, + { + Name: "invalid one to one chat, wrong public key", + Valid: false, + Chat: Chat{ + ID: "0xnotvalid", + Name: "", + ChatType: ChatTypeOneToOne, + }, + }, + } + + for _, tc := range testCases { + s.Run(tc.Name, func() { + err := tc.Chat.Validate() + if tc.Valid { + s.Require().NoError(err) + } else { + s.Require().Error(err) + } + }) + } + +} diff --git a/protocol/identity/alias/generate.go b/protocol/identity/alias/generate.go index c3172d81a..8c175142a 100644 --- a/protocol/identity/alias/generate.go +++ b/protocol/identity/alias/generate.go @@ -24,6 +24,7 @@ func generate(seed uint64) string { // GenerateFromPublicKey returns the 3 words name given an *ecdsa.PublicKey func GenerateFromPublicKey(publicKey *ecdsa.PublicKey) string { + // Here we truncate the public key to the least significant 64 bits return generate(uint64(publicKey.X.Int64())) } diff --git a/protocol/messenger.go b/protocol/messenger.go index c4b456b4a..074e96d2b 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -401,6 +401,11 @@ func (m *Messenger) Init() error { return err } for _, chat := range chats { + if err := chat.Validate(); err != nil { + logger.Warn("failed to validate chat", zap.Error(err)) + continue + } + m.allChats[chat.ID] = chat if !chat.Active { continue diff --git a/protocol/messenger_test.go b/protocol/messenger_test.go index bda53d19d..510e7d5e5 100644 --- a/protocol/messenger_test.go +++ b/protocol/messenger_test.go @@ -183,6 +183,7 @@ func (s *MessengerSuite) TestInit() { key2, err := crypto.GenerateKey() s.Require().NoError(err) groupChat := Chat{ + ID: "some-id", ChatType: ChatTypePrivateGroupChat, Active: true, Members: []ChatMember{ diff --git a/protocol/persistence.go b/protocol/persistence.go index 3207a7158..411836bd3 100644 --- a/protocol/persistence.go +++ b/protocol/persistence.go @@ -22,6 +22,10 @@ type sqlitePersistence struct { } func (db sqlitePersistence) SaveChat(chat Chat) error { + err := chat.Validate() + if err != nil { + return err + } return db.saveChat(nil, chat) } diff --git a/vendor/github.com/status-im/status-go/protocol/chat.go b/vendor/github.com/status-im/status-go/protocol/chat.go index e6372fdca..c49e27a8c 100644 --- a/vendor/github.com/status-im/status-go/protocol/chat.go +++ b/vendor/github.com/status-im/status-go/protocol/chat.go @@ -5,6 +5,7 @@ import ( "crypto/sha1" "encoding/hex" "encoding/json" + "errors" "math/rand" "github.com/status-im/status-go/eth-node/crypto" @@ -79,6 +80,22 @@ func (c *Chat) Public() bool { return c.ChatType == ChatTypePublic } +func (c *Chat) OneToOne() bool { + return c.ChatType == ChatTypeOneToOne +} + +func (c *Chat) Validate() error { + if c.ID == "" { + return errors.New("chatID can't be blank") + } + + if c.OneToOne() { + _, err := c.PublicKey() + return err + } + return nil +} + func (c *Chat) MarshalJSON() ([]byte, error) { type ChatAlias Chat item := struct { diff --git a/vendor/github.com/status-im/status-go/protocol/identity/alias/generate.go b/vendor/github.com/status-im/status-go/protocol/identity/alias/generate.go index c3172d81a..8c175142a 100644 --- a/vendor/github.com/status-im/status-go/protocol/identity/alias/generate.go +++ b/vendor/github.com/status-im/status-go/protocol/identity/alias/generate.go @@ -24,6 +24,7 @@ func generate(seed uint64) string { // GenerateFromPublicKey returns the 3 words name given an *ecdsa.PublicKey func GenerateFromPublicKey(publicKey *ecdsa.PublicKey) string { + // Here we truncate the public key to the least significant 64 bits return generate(uint64(publicKey.X.Int64())) } diff --git a/vendor/github.com/status-im/status-go/protocol/messenger.go b/vendor/github.com/status-im/status-go/protocol/messenger.go index c4b456b4a..074e96d2b 100644 --- a/vendor/github.com/status-im/status-go/protocol/messenger.go +++ b/vendor/github.com/status-im/status-go/protocol/messenger.go @@ -401,6 +401,11 @@ func (m *Messenger) Init() error { return err } for _, chat := range chats { + if err := chat.Validate(); err != nil { + logger.Warn("failed to validate chat", zap.Error(err)) + continue + } + m.allChats[chat.ID] = chat if !chat.Active { continue diff --git a/vendor/github.com/status-im/status-go/protocol/persistence.go b/vendor/github.com/status-im/status-go/protocol/persistence.go index 3207a7158..411836bd3 100644 --- a/vendor/github.com/status-im/status-go/protocol/persistence.go +++ b/vendor/github.com/status-im/status-go/protocol/persistence.go @@ -22,6 +22,10 @@ type sqlitePersistence struct { } func (db sqlitePersistence) SaveChat(chat Chat) error { + err := chat.Validate() + if err != nil { + return err + } return db.saveChat(nil, chat) }