diff --git a/api/auth.go b/api/auth.go index d7a5cc362ea49dc9108e220d05c5fd45eeb5586f..550b6ebfa0965a7aa4345fd2318f5314c48acbc3 100644 --- a/api/auth.go +++ b/api/auth.go @@ -178,5 +178,5 @@ func (c *Client) GetRelationshipFingerprint(partner *id.ID) (string, error) { partner) } - return m.GetConnectionFingerprint(), nil + return m.ConnectionFingerprint(), nil } diff --git a/cmd/root.go b/cmd/root.go index a3bd31ef5c22245504283d8901ef2f3c3c315c95..a9c6005811a043ebd469d011361be42e772408a3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -13,8 +13,10 @@ import ( "encoding/binary" "encoding/hex" "encoding/json" + "errors" "fmt" "gitlab.com/elixxir/client/cmix" + "io/fs" "io/ioutil" "log" "os" @@ -536,7 +538,7 @@ func createClient() *api.Client { backupPass := []byte(viper.GetString("backupPass")) // create a new client if none exist - if _, err := os.Stat(storeDir); os.IsNotExist(err) { + if _, err := os.Stat(storeDir); errors.Is(err, fs.ErrNotExist) { // Load NDF ndfJSON, err := ioutil.ReadFile(viper.GetString("ndf")) if err != nil { diff --git a/cmix/follow.go b/cmix/follow.go index 5bafb3718f4d16e59c006d932b8e567fb0145be4..b3a5bc66285bf696893974af9f2c9d68f58ec0ea 100644 --- a/cmix/follow.go +++ b/cmix/follow.go @@ -24,9 +24,11 @@ package cmix import ( "bytes" - "crypto/rand" "encoding/binary" "fmt" + "sync/atomic" + "time" + jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/cmix/identity/receptionID/store" "gitlab.com/elixxir/client/stoppable" @@ -37,8 +39,6 @@ import ( "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" - "sync/atomic" - "time" ) const ( @@ -424,10 +424,12 @@ func (c *client) follow(report ClientErrorReport, rng csprng.Source, // getFakeEarliestRound generates a random earliest round for a fake identity. func (c *client) getFakeEarliestRound() id.Round { - b, err := csprng.Generate(8, rand.Reader) + rng := c.rng.GetStream() + b, err := csprng.Generate(8, rng) if err != nil { - jww.FATAL.Panicf("Could not get random number: %+v", err) + jww.FATAL.Panicf("Could not get random number: %v", err) } + rng.Close() rangeVal := binary.LittleEndian.Uint64(b) % 800 diff --git a/cmix/identity/tracker.go b/cmix/identity/tracker.go index 93cde203c4ca3f3f55516783a14fddcb4d0e329e..1622fc61dafcc4d258ed68a46c3cf93ef7979443 100644 --- a/cmix/identity/tracker.go +++ b/cmix/identity/tracker.go @@ -11,7 +11,7 @@ import ( "encoding/json" "github.com/pkg/errors" "io" - "os" + "io/fs" "sync" "time" @@ -85,7 +85,7 @@ func NewOrLoadTracker(session storage.Session, addrSpace address.Space) *manager // Load this structure err := t.load() - if err != nil && os.IsNotExist(err) { + if err != nil && errors.Is(err, fs.ErrNotExist) { oldTimestamp, err2 := getOldTimestampStore(t.session) if err2 == nil { jww.WARN.Printf("No tracked identities found, creating a new " + diff --git a/e2e/interface.go b/e2e/interface.go index 03e9d312a692dfd9649f8ce4e4fe2521a3bb82eb..43644636361a97c310f60ca0cf2ca1651fee1078 100644 --- a/e2e/interface.go +++ b/e2e/interface.go @@ -107,11 +107,7 @@ type Handler interface { // AddPartner adds a partner. Automatically creates both send // and receive sessions using the passed cryptographic data - // and per the parameters sent If an alternate ID public key - // are to be used for this relationship, then pass them in, - // otherwise, leave myID and myPrivateKey nil If temporary is - // true, an alternate ram kv will be used for storage and the - // relationship will not survive a reset + // and per the parameters sent AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, @@ -119,13 +115,11 @@ type Handler interface { receiveParams session.Params) (partner.Manager, error) // GetPartner returns the partner per its ID, if it exists - // myID is your ID in the relationship, if left blank, it will - // assume to be your defaultID + // myID is your ID in the relationship GetPartner(partnerID *id.ID) (partner.Manager, error) // DeletePartner removes the associated contact from the E2E store - // myID is your ID in the relationship, if left blank, it will - // assume to be your defaultID + // myID is your ID in the relationship DeletePartner(partnerId *id.ID) error // GetAllPartnerIDs returns a list of all partner IDs that the user has diff --git a/e2e/manager.go b/e2e/manager.go index 853303bbe20633da76ff329ee6f6f4a99ec769e1..38756fc168d8fad2cc65fe3b23db14b494b7f3c7 100644 --- a/e2e/manager.go +++ b/e2e/manager.go @@ -2,7 +2,6 @@ package e2e import ( "encoding/json" - "fmt" "strings" "time" @@ -95,7 +94,6 @@ func LoadLegacy(kv *versioned.KV, net cmix.Client, myID *id.ID, // this would be a case where LoadLegacy is most likely not the correct // code-path the caller should be following. if _, err := kv.Get(e2eRekeyParamsKey, e2eRekeyParamsVer); err != nil && !strings.Contains(err.Error(), "object not found") { - fmt.Printf("err: %v", err) return nil, errors.New("E2E rekey params are already on disk, " + "LoadLegacy should not be called") } diff --git a/e2e/manager_test.go b/e2e/manager_test.go index 5367f9b3fd89dd7f562ada8fa2be9dbeb04b0999..54a04e1ec096c0106cc5711982c46eb0524ed8e3 100644 --- a/e2e/manager_test.go +++ b/e2e/manager_test.go @@ -124,16 +124,16 @@ func TestLoadLegacy(t *testing.T) { t.Errorf("Partner %d does not exist in handler.", legacyPartner.partnerId) } - if !bytes.Equal(partnerManager.GetSendRelationshipFingerprint(), legacyPartner.sendFP) { + if !bytes.Equal(partnerManager.SendRelationshipFingerprint(), legacyPartner.sendFP) { t.Fatalf("Send relationship fingerprint pulled from legacy does not match expected data."+ "\nExpected: %v"+ - "\nReceived: %v", legacyPartner.sendFP, partnerManager.GetSendRelationshipFingerprint()) + "\nReceived: %v", legacyPartner.sendFP, partnerManager.SendRelationshipFingerprint()) } - if !bytes.Equal(partnerManager.GetReceiveRelationshipFingerprint(), legacyPartner.recieveFp) { + if !bytes.Equal(partnerManager.ReceiveRelationshipFingerprint(), legacyPartner.recieveFp) { t.Fatalf("Receive relationship fingerprint pulled from legacy does not match expected data."+ "\nExpected: %v"+ - "\nReceived: %v", legacyPartner.sendFP, partnerManager.GetSendRelationshipFingerprint()) + "\nReceived: %v", legacyPartner.sendFP, partnerManager.SendRelationshipFingerprint()) } } diff --git a/e2e/parse/conversation/partner.go b/e2e/parse/conversation/partner.go index 28349a8edba998c8c47c9f8225a678aaaafd20a6..06155c697b6674c16261cb84af74ccb714feb69c 100644 --- a/e2e/parse/conversation/partner.go +++ b/e2e/parse/conversation/partner.go @@ -14,8 +14,8 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" + "io/fs" "math" - "os" "strings" "sync" ) @@ -51,7 +51,7 @@ type conversationDisk struct { // saved to KV, and returned. func LoadOrMakeConversation(kv *versioned.KV, partner *id.ID) *Conversation { c, err := loadConversation(kv, partner) - if err != nil && !(os.IsNotExist(err) || strings.Contains(err.Error(), "object not found")) { + if err != nil && !(errors.Is(err, fs.ErrNotExist) || strings.Contains(err.Error(), "object not found")) { jww.FATAL.Panicf("Failed to load conversation from storage: %+v", err) } else if c == nil { // Create new conversation and save to KV if one does not exist diff --git a/e2e/ratchet/partner/interface.go b/e2e/ratchet/partner/interface.go index 06a3aadc624daad3324144d30c9790679e8700d6..02315b1ff7e4f63845f79a9feee3bd8668e79656 100644 --- a/e2e/ratchet/partner/interface.go +++ b/e2e/ratchet/partner/interface.go @@ -9,40 +9,61 @@ import ( "gitlab.com/xx_network/primitives/id" ) +// Manager create and manages both E2E send and receive sessions using the passed cryptographic data type Manager interface { - //accessors - GetPartnerID() *id.ID - GetMyID() *id.ID - GetMyOriginPrivateKey() *cyclic.Int - GetPartnerOriginPublicKey() *cyclic.Int + // PartnerId returns the ID of the E2E partner + PartnerId() *id.ID + // MyId returns my ID used for the E2E relationship + MyId() *id.ID + // MyRootPrivateKey returns first private key in the DAG + MyRootPrivateKey() *cyclic.Int + // PartnerRootPublicKey returns the partner's first public key in the DAG + PartnerRootPublicKey() *cyclic.Int + // SendRelationshipFingerprint returns the fingerprint of the send session + SendRelationshipFingerprint() []byte + // ReceiveRelationshipFingerprint returns the fingerprint of the receive session + ReceiveRelationshipFingerprint() []byte + // ConnectionFingerprint returns a unique fingerprint for an E2E relationship in string format + ConnectionFingerprint() ConnectionFp + // Contact returns the contact of the E2E partner + Contact() contact.Contact - GetSendRelationshipFingerprint() []byte - GetReceiveRelationshipFingerprint() []byte - - GetConnectionFingerprintBytes() []byte - GetConnectionFingerprint() string - GetContact() contact.Contact - - //sending and receving + // PopSendCypher returns the key which is most likely to be successful for sending PopSendCypher() (*session.Cypher, error) + // PopRekeyCypher returns a key which should be used for rekeying PopRekeyCypher() (*session.Cypher, error) - //Ratcheting + // NewReceiveSession creates a new Receive session using the latest private key + // this user has sent and the new public key received from the partner. If the + // session already exists, then it will not be overwritten and the extant + // session will be returned with the bool set to true denoting a duplicate. This + // allows for support of duplicate key exchange triggering. NewReceiveSession(partnerPubKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey, e2eParams session.Params, source *session.Session) (*session.Session, bool) + // NewSendSession creates a new Send session using the latest public key + // received from the partner and a new private key for the user. Passing in a + // private key is optional. A private key will be generated if none is passed. NewSendSession(myDHPrivKey *cyclic.Int, mySIDHPrivateKey *sidh.PrivateKey, e2eParams session.Params, source *session.Session) *session.Session + // GetSendSession gets the Send session of the passed ID. Returns nil if no session is found. GetSendSession(sid session.SessionID) *session.Session - - //state machine + //GetReceiveSession gets the Receive session of the passed ID. Returns nil if no session is found. GetReceiveSession(sid session.SessionID) *session.Session + + // Confirm sets the passed session ID as confirmed and cleans up old sessions Confirm(sid session.SessionID) error + + // TriggerNegotiations returns a list of session that need rekeys TriggerNegotiations() []*session.Session - //services + // MakeService Returns a service interface with the + // appropriate identifier for who is being sent to. Will populate + // the metadata with the partner MakeService(tag string) message.Service - //storage + // Delete removes the relationship between the partner + // and deletes the Send and Receive sessions. This includes the + // sessions and the key vectors Delete() error } diff --git a/e2e/ratchet/partner/manager.go b/e2e/ratchet/partner/manager.go index 789bb3b2e74bc3d0864e423fa4859a3241a4d1d3..fbb33af91e1cb1b00508cb471422a41e925d46dd 100644 --- a/e2e/ratchet/partner/manager.go +++ b/e2e/ratchet/partner/manager.go @@ -8,9 +8,9 @@ package partner import ( - "bytes" "encoding/base64" "fmt" + "gitlab.com/elixxir/crypto/e2e" "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" @@ -23,13 +23,14 @@ import ( "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/primitives/id" - "golang.org/x/crypto/blake2b" ) const managerPrefix = "Manager{partner:%s}" const originMyPrivKeyKey = "originMyPrivKey" const originPartnerPubKey = "originPartnerPubKey" +const relationshipFpLength = 15 +// Implements the partner.Manager interface type manager struct { kv *versioned.KV @@ -93,6 +94,21 @@ func NewManager(kv *versioned.KV, myID, partnerID *id.ID, myPrivKey, return m } +// ConnectionFp represents a Partner connection fingerprint +type ConnectionFp struct { + fingerprint []byte +} + +func (c ConnectionFp) Bytes() []byte { + return c.fingerprint +} + +func (c ConnectionFp) String() string { + // Base 64 encode hash and truncate + return base64.StdEncoding.EncodeToString( + c.fingerprint)[:relationshipFpLength] +} + //LoadManager loads a relationship and all buffers and sessions from disk func LoadManager(kv *versioned.KV, myID, partnerID *id.ID, cyHandler session.CypherHandler, grp *cyclic.Group, @@ -231,26 +247,24 @@ func (m *manager) NewSendSession(myPrivKey *cyclic.Int, sourceSession.GetID(), session.Sending, e2eParams) } -// PopSendCypher gets the correct session to Send with depending on the type -// of Send. +// PopSendCypher returns the key which is most likely to be successful for sending func (m *manager) PopSendCypher() (*session.Cypher, error) { return m.send.getKeyForSending() } -// PopRekeyCypher gets the correct session to Send with depending on the type -// of Send. +// PopRekeyCypher returns a key which should be used for rekeying func (m *manager) PopRekeyCypher() (*session.Cypher, error) { return m.send.getKeyForRekey() } -// GetPartnerID returns a copy of the ID of the partner. -func (m *manager) GetPartnerID() *id.ID { +// PartnerId returns a copy of the ID of the partner. +func (m *manager) PartnerId() *id.ID { return m.partner.DeepCopy() } -// GetMyID returns a copy of the ID used as self. -func (m *manager) GetMyID() *id.ID { +// MyId returns a copy of the ID used as self. +func (m *manager) MyId() *id.ID { return m.myID.DeepCopy() } @@ -266,15 +280,13 @@ func (m *manager) GetReceiveSession(sid session.SessionID) *session.Session { return m.receive.GetByID(sid) } -// GetSendRelationshipFingerprint gets the Send session of the passed ID. Returns nil if no -// session is found. -func (m *manager) GetSendRelationshipFingerprint() []byte { +// SendRelationshipFingerprint +func (m *manager) SendRelationshipFingerprint() []byte { return m.send.fingerprint } -// GetReceiveRelationshipFingerprint gets the receive session of the passed ID. -// Returns nil if no session is found. -func (m *manager) GetReceiveRelationshipFingerprint() []byte { +// ReceiveRelationshipFingerprint +func (m *manager) ReceiveRelationshipFingerprint() []byte { return m.receive.fingerprint } @@ -283,52 +295,23 @@ func (m *manager) Confirm(sid session.SessionID) error { return m.send.Confirm(sid) } -// TriggerNegotiations returns a list of key exchange operations if any are -// necessary. +// TriggerNegotiations returns a list of key exchange operations if any are necessary. func (m *manager) TriggerNegotiations() []*session.Session { return m.send.TriggerNegotiation() } -func (m *manager) GetMyOriginPrivateKey() *cyclic.Int { +func (m *manager) MyRootPrivateKey() *cyclic.Int { return m.originMyPrivKey.DeepCopy() } -func (m *manager) GetPartnerOriginPublicKey() *cyclic.Int { +func (m *manager) PartnerRootPublicKey() *cyclic.Int { return m.originPartnerPubKey.DeepCopy() } -const relationshipFpLength = 15 - -// GetRelationshipFingerprint returns a unique fingerprint for an E2E -// relationship. The fingerprint is a base 64 encoded hash of of the two -// relationship fingerprints truncated to 15 characters. -func (m *manager) GetConnectionFingerprint() string { - - // Base 64 encode hash and truncate - return base64.StdEncoding.EncodeToString( - m.GetConnectionFingerprintBytes())[:relationshipFpLength] -} - -// GetRelationshipFingerprintBytes returns a unique fingerprint for an E2E -// relationship. used for the e2e preimage. -func (m *manager) GetConnectionFingerprintBytes() []byte { - // Sort fingerprints - var fps [][]byte - - if bytes.Compare(m.receive.fingerprint, m.send.fingerprint) == 1 { - fps = [][]byte{m.send.fingerprint, m.receive.fingerprint} - } else { - fps = [][]byte{m.receive.fingerprint, m.send.fingerprint} - } - - // Hash fingerprints - h, _ := blake2b.New256(nil) - for _, fp := range fps { - h.Write(fp) - } - - // Base 64 encode hash and truncate - return h.Sum(nil) +// ConnectionFingerprint returns a unique fingerprint for an E2E +// relationship used for the e2e preimage. +func (m *manager) ConnectionFingerprint() ConnectionFp { + return ConnectionFp{fingerprint: e2e.GenerateConnectionFingerprint(m.send.fingerprint, m.receive.fingerprint)} } // MakeService Returns a service interface with the @@ -336,19 +319,18 @@ func (m *manager) GetConnectionFingerprintBytes() []byte { // the metadata with the partner func (m *manager) MakeService(tag string) message.Service { return message.Service{ - Identifier: m.GetConnectionFingerprintBytes(), + Identifier: m.ConnectionFingerprint().Bytes(), Tag: tag, Metadata: m.partner[:], } } -// GetContact assembles and returns a contact.Contact with the partner's ID -// and DH key. -func (m *manager) GetContact() contact.Contact { +// Contact assembles and returns a contact.Contact with the partner's ID and DH key. +func (m *manager) Contact() contact.Contact { // Assemble Contact return contact.Contact{ - ID: m.GetPartnerID(), - DhPubKey: m.GetPartnerOriginPublicKey(), + ID: m.PartnerId(), + DhPubKey: m.PartnerRootPublicKey(), } } diff --git a/e2e/ratchet/partner/manager_test.go b/e2e/ratchet/partner/manager_test.go index 944121e069191ebd0946df8e33548f32fb7e64fa..dab364dec3727cc926d2aa1cabb46e5c445cc330 100644 --- a/e2e/ratchet/partner/manager_test.go +++ b/e2e/ratchet/partner/manager_test.go @@ -9,7 +9,6 @@ package partner import ( "bytes" - "encoding/base64" "math/rand" "reflect" "testing" @@ -23,7 +22,6 @@ import ( "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/primitives/id" - "golang.org/x/crypto/blake2b" ) // Tests happy path of newManager. @@ -243,10 +241,10 @@ func TestManager_GetKeyForSending_Error(t *testing.T) { func TestManager_GetPartnerID(t *testing.T) { m, _ := newTestManager(t) - pid := m.GetPartnerID() + pid := m.PartnerId() if !m.partner.Cmp(pid) { - t.Errorf("GetPartnerID() returned incorrect partner ID."+ + t.Errorf("PartnerId() returned incorrect partner ID."+ "\n\texpected: %s\n\treceived: %s", m.partner, pid) } } @@ -257,10 +255,10 @@ func TestManager_GetMyID(t *testing.T) { m := &manager{myID: myId} - receivedMyId := m.GetMyID() + receivedMyId := m.MyId() if !myId.Cmp(receivedMyId) { - t.Errorf("GetMyID() returned incorrect partner ID."+ + t.Errorf("MyId() returned incorrect partner ID."+ "\n\texpected: %s\n\treceived: %s", myId, receivedMyId) } } @@ -336,73 +334,11 @@ func TestManager_TriggerNegotiations(t *testing.T) { } } -// Unit test of Manager.GetRelationshipFingerprint. -func TestManager_GetRelationshipFingerprint(t *testing.T) { - m, _ := newTestManager(t) - m.receive.fingerprint = []byte{5} - m.send.fingerprint = []byte{10} - h, _ := blake2b.New256(nil) - h.Write(append(m.receive.fingerprint, m.send.fingerprint...)) - expected := base64.StdEncoding.EncodeToString(h.Sum(nil))[:relationshipFpLength] - - fp := m.GetConnectionFingerprint() - if fp != expected { - t.Errorf("GetConnectionFingerprint did not return the expected "+ - "fingerprint.\nexpected: %s\nreceived: %s", expected, fp) - } - - // Flip the order and show that the output is the same. - m.receive.fingerprint, m.send.fingerprint = m.send.fingerprint, m.receive.fingerprint - - fp = m.GetConnectionFingerprint() - if fp != expected { - t.Errorf("GetConnectionFingerprint did not return the expected "+ - "fingerprint.\nexpected: %s\nreceived: %s", expected, fp) - } -} - -// Tests the consistency of the output of Manager.GetRelationshipFingerprint. -func TestManager_GetRelationshipFingerprint_Consistency(t *testing.T) { - m, _ := newTestManager(t) - prng := rand.New(rand.NewSource(42)) - expectedFps := []string{ - "GmeTCfxGOqRqeID", "gbpJjHd3tIe8BKy", "2/ZdG+WNzODJBiF", - "+V1ySeDLQfQNSkv", "23OMC+rBmCk+gsu", "qHu5MUVs83oMqy8", - "kuXqxsezI0kS9Bc", "SlEhsoZ4BzAMTtr", "yG8m6SPQfV/sbTR", - "j01ZSSm762TH7mj", "SKFDbFvsPcohKPw", "6JB5HK8DHGwS4uX", - "dU3mS1ujduGD+VY", "BDXAy3trbs8P4mu", "I4HoXW45EwWR0oD", - "661YH2l2jfOkHbA", "cSS9ZyTOQKVx67a", "ojfubzDIsMNYc/t", - "2WrEw83Yz6Rhq9I", "TQILxBIUWMiQS2j", "rEqdieDTXJfCQ6I", - } - - for i, expected := range expectedFps { - prng.Read(m.receive.fingerprint) - prng.Read(m.send.fingerprint) - - fp := m.GetConnectionFingerprint() - if fp != expected { - t.Errorf("GetConnectionFingerprint did not return the expected "+ - "fingerprint (%d).\nexpected: %s\nreceived: %s", i, expected, fp) - } - - // Flip the order and show that the output is the same. - m.receive.fingerprint, m.send.fingerprint = m.send.fingerprint, m.receive.fingerprint - - fp = m.GetConnectionFingerprint() - if fp != expected { - t.Errorf("GetConnectionFingerprint did not return the expected "+ - "fingerprint (%d).\nexpected: %s\nreceived: %s", i, expected, fp) - } - - // fmt.Printf("\"%s\",\n", fp) // Uncomment to reprint expected values - } -} - func TestManager_MakeService(t *testing.T) { m, _ := newTestManager(t) tag := "hunter2" expected := message.Service{ - Identifier: m.GetConnectionFingerprintBytes(), + Identifier: m.ConnectionFingerprint().Bytes(), Tag: tag, Metadata: m.partner[:], } diff --git a/e2e/ratchet/partner/relationship.go b/e2e/ratchet/partner/relationship.go index 6c54b5921d1ced8f68f96d7f8f51ad06acf984ee..56b08a57137ac48f0fe27b953452dee0bbe2c01a 100644 --- a/e2e/ratchet/partner/relationship.go +++ b/e2e/ratchet/partner/relationship.go @@ -248,7 +248,7 @@ func (r *relationship) GetNewest() *session.Session { return r.sessions[0] } -// returns the key which is most likely to be successful for sending +// returns the key which is most likely to be successful for sending func (r *relationship) getKeyForSending() (*session.Cypher, error) { r.sendMux.Lock() defer r.sendMux.Unlock() @@ -311,11 +311,9 @@ func (r *relationship) getSessionForSending() *session.Session { return nil } -// todo - doscstring -// returns a list of session that need rekeys. Nil instances mean a new rekey -// from scratch +// TriggerNegotiation returns a list of session that need rekeys. Nil instances mean a new rekey from scratch func (r *relationship) TriggerNegotiation() []*session.Session { - //dont need to take the lock due to the use of a copy of the buffer + // Don't need to take the lock due to the use of a copy of the buffer sessions := r.getInternalBufferShallowCopy() var instructions []*session.Session for _, ses := range sessions { @@ -379,10 +377,7 @@ func (r *relationship) GetByID(id session.SessionID) *session.Session { return r.sessionByID[id] } -// todo - doscstring -// sets the passed session ID as confirmed. Call "GetSessionRotation" after -// to get any sessions that are to be deleted and then "DeleteSession" to -// remove them +// Confirm sets the passed session ID as confirmed and cleans up old sessions func (r *relationship) Confirm(id session.SessionID) error { r.mux.Lock() defer r.mux.Unlock() @@ -409,7 +404,7 @@ func (r *relationship) getInternalBufferShallowCopy() []*session.Session { return r.sessions } -// todo - doscstring +// clean deletes old confirmed sessions func (r *relationship) clean() { numConfirmed := uint(0) @@ -420,7 +415,7 @@ func (r *relationship) clean() { for _, s := range r.sessions { if s.IsConfirmed() { numConfirmed++ - //if the number of newer confirmed is + // if the number of newer confirmed is // sufficient, delete the confirmed if numConfirmed > maxUnconfirmed { delete(r.sessionByID, s.GetID()) @@ -432,7 +427,7 @@ func (r *relationship) clean() { newSessions = append(newSessions, s) } - //only do the update and save if changes occured + //only do the update and save if changes occurred if editsMade { r.sessions = newSessions diff --git a/e2e/ratchet/partner/session/session.go b/e2e/ratchet/partner/session/session.go index a62cf91618ce7706b0838b7ec5c0ff6d816da5a0..234c8b357a58f8bb5b328a49e631fc41effe44f6 100644 --- a/e2e/ratchet/partner/session/session.go +++ b/e2e/ratchet/partner/session/session.go @@ -515,7 +515,6 @@ func (s *Session) NegotiationStatus() Negotiation { // IsConfirmed checks if the session has been confirmed func (s *Session) IsConfirmed() bool { c := s.NegotiationStatus() - //fmt.Println(c) return c >= Confirmed } diff --git a/e2e/ratchet/partner/utils.go b/e2e/ratchet/partner/utils.go index 55a25ab9b2f9da82f655eed4dcf85b2331fffa9a..656a847fc5d5324e8b3181be9385c908a14338fa 100644 --- a/e2e/ratchet/partner/utils.go +++ b/e2e/ratchet/partner/utils.go @@ -36,39 +36,39 @@ func NewTestManager(partnerId *id.ID, partnerPubKey, myPrivKey *cyclic.Int, t *t return &testManager{partnerId: partnerId, partnerPubKey: partnerPubKey, myPrivKey: myPrivKey} } -func (p *testManager) GetPartnerID() *id.ID { +func (p *testManager) PartnerId() *id.ID { return p.partnerId } -func (p *testManager) GetMyID() *id.ID { +func (p *testManager) MyId() *id.ID { panic("implement me") } -func (p *testManager) GetMyOriginPrivateKey() *cyclic.Int { +func (p *testManager) MyRootPrivateKey() *cyclic.Int { return p.myPrivKey } -func (p *testManager) GetPartnerOriginPublicKey() *cyclic.Int { +func (p *testManager) PartnerRootPublicKey() *cyclic.Int { return p.partnerPubKey } -func (p *testManager) GetSendRelationshipFingerprint() []byte { +func (p *testManager) SendRelationshipFingerprint() []byte { panic("implement me") } -func (p *testManager) GetReceiveRelationshipFingerprint() []byte { +func (p *testManager) ReceiveRelationshipFingerprint() []byte { panic("implement me") } -func (p *testManager) GetConnectionFingerprintBytes() []byte { +func (p *testManager) ConnectionFingerprintBytes() []byte { panic("implement me") } -func (p *testManager) GetConnectionFingerprint() string { +func (p *testManager) ConnectionFingerprint() string { panic("implement me") } -func (p *testManager) GetContact() contact.Contact { +func (p *testManager) Contact() contact.Contact { panic("implement me") } diff --git a/e2e/ratchet/ratchet.go b/e2e/ratchet/ratchet.go index 3bc73f3b953bb3b3b1f83037049335803ccc5340..92ff4ba4250d23138c5559bd90cc4e5a584080ce 100644 --- a/e2e/ratchet/ratchet.go +++ b/e2e/ratchet/ratchet.go @@ -175,7 +175,7 @@ func (r *Ratchet) GetAllPartnerIDs() []*id.ID { partnerIDs := make([]*id.ID, 0, len(r.managers)) for _, m := range r.managers { - partnerIDs = append(partnerIDs, m.GetPartnerID()) + partnerIDs = append(partnerIDs, m.PartnerId()) } return partnerIDs diff --git a/e2e/ratchet/storage.go b/e2e/ratchet/storage.go index 5ffea5fa63b6f9fcd685be70a8baae5feac592a3..cd285816f3fb055ac6d2fe3d98b13402bf73e62a 100644 --- a/e2e/ratchet/storage.go +++ b/e2e/ratchet/storage.go @@ -87,7 +87,7 @@ func (r *Ratchet) marshal() ([]byte, error) { contacts := make([]id.ID, len(r.managers)) index := 0 - for rid, _ := range r.managers { + for rid := range r.managers { contacts[index] = rid index++ } @@ -118,10 +118,10 @@ func (r *Ratchet) unmarshal(b []byte) error { " %s: %s", partnerID, err.Error()) } - if !manager.GetPartnerID().Cmp(partnerID) { + if !manager.PartnerId().Cmp(partnerID) { jww.FATAL.Panicf("Loaded manager with the wrong "+ "partner ID: \n\t loaded: %s \n\t present: %s", - partnerID, manager.GetPartnerID()) + partnerID, manager.PartnerId()) } //add services for the manager diff --git a/e2e/ratchet/utils_test.go b/e2e/ratchet/utils_test.go index c3497872084493d7e5c8e6dc65997365ad191c3b..02c9ed79297487e013c72174aea994d2840ccb3e 100644 --- a/e2e/ratchet/utils_test.go +++ b/e2e/ratchet/utils_test.go @@ -45,37 +45,37 @@ func makeTestRatchet() (*Ratchet, *versioned.KV, error) { func managersEqual(expected, received partner.Manager, t *testing.T) bool { equal := true - if !reflect.DeepEqual(expected.GetPartnerID(), received.GetPartnerID()) { + if !reflect.DeepEqual(expected.PartnerId(), received.PartnerId()) { t.Errorf("Did not Receive expected Manager.partnerID."+ "\n\texpected: %+v\n\treceived: %+v", - expected.GetPartnerID(), received.GetPartnerID()) + expected.PartnerId(), received.PartnerId()) equal = false } - if !strings.EqualFold(expected.GetConnectionFingerprint(), received.GetConnectionFingerprint()) { + if !strings.EqualFold(expected.ConnectionFingerprint(), received.ConnectionFingerprint()) { t.Errorf("Did not Receive expected Manager.Receive."+ "\n\texpected: %+v\n\treceived: %+v", - expected.GetConnectionFingerprint(), received.GetConnectionFingerprint()) + expected.ConnectionFingerprint(), received.ConnectionFingerprint()) equal = false } - if !reflect.DeepEqual(expected.GetMyID(), received.GetMyID()) { + if !reflect.DeepEqual(expected.MyId(), received.MyId()) { t.Errorf("Did not Receive expected Manager.myId."+ "\n\texpected: %+v\n\treceived: %+v", - expected.GetMyID(), received.GetPartnerID()) + expected.MyId(), received.PartnerId()) equal = false } - if !reflect.DeepEqual(expected.GetMyOriginPrivateKey(), received.GetMyOriginPrivateKey()) { + if !reflect.DeepEqual(expected.MyRootPrivateKey(), received.MyRootPrivateKey()) { t.Errorf("Did not Receive expected Manager.MyPrivateKey."+ "\n\texpected: %+v\n\treceived: %+v", - expected.GetMyOriginPrivateKey(), received.GetMyOriginPrivateKey()) + expected.MyRootPrivateKey(), received.MyRootPrivateKey()) equal = false } - if !reflect.DeepEqual(expected.GetSendRelationshipFingerprint(), received.GetSendRelationshipFingerprint()) { + if !reflect.DeepEqual(expected.SendRelationshipFingerprint(), received.SendRelationshipFingerprint()) { t.Errorf("Did not Receive expected Manager.SendRelationshipFingerprint."+ "\n\texpected: %+v\n\treceived: %+v", - expected.GetSendRelationshipFingerprint(), received.GetSendRelationshipFingerprint()) + expected.SendRelationshipFingerprint(), received.SendRelationshipFingerprint()) equal = false } diff --git a/e2e/rekey/confirm.go b/e2e/rekey/confirm.go index a7094d9254ed15390d66ce0542109169341019d3..b6ae0a6ddaec07fa19dab7b8e86a0d374ad27b50 100644 --- a/e2e/rekey/confirm.go +++ b/e2e/rekey/confirm.go @@ -74,11 +74,11 @@ func handleConfirm(ratchet *ratchet.Ratchet, confirmation receive.Message) { jww.WARN.Printf("[REKEY] Failed to set the negotiation status for the "+ "confirmation of session %s from partner %s. This is expected in "+ "some edge cases but could be a sign of an issue if it persists: %s", - confirmedSession, partner.GetPartnerID(), err) + confirmedSession, partner.PartnerId(), err) } jww.DEBUG.Printf("[REKEY] handled confirmation for session "+ - "%s from partner %s.", confirmedSession, partner.GetPartnerID()) + "%s from partner %s.", confirmedSession, partner.PartnerId()) } func unmarshalConfirm(payload []byte) (session2.SessionID, error) { diff --git a/e2e/rekey/utils_test.go b/e2e/rekey/utils_test.go index 706d4b7bc19371cb771a845829bf507074e3b489..c7296ecd26fe92a207e39cf43140805c4af6710c 100644 --- a/e2e/rekey/utils_test.go +++ b/e2e/rekey/utils_test.go @@ -17,9 +17,9 @@ import ( "gitlab.com/elixxir/client/catalog" "gitlab.com/elixxir/client/cmix" "gitlab.com/elixxir/client/cmix/gateway" - "gitlab.com/elixxir/client/cmix/rounds" "gitlab.com/elixxir/client/cmix/identity" "gitlab.com/elixxir/client/cmix/message" + "gitlab.com/elixxir/client/cmix/rounds" session2 "gitlab.com/elixxir/client/e2e/ratchet/partner/session" "gitlab.com/elixxir/client/e2e/receive" "gitlab.com/elixxir/client/stoppable" @@ -84,8 +84,8 @@ func testSendE2E(mt catalog.MessageType, recipient *id.ID, print(err) } - alicePrivKey := alicePartner.GetMyOriginPrivateKey() - bobPubKey := bobPartner.GetMyOriginPrivateKey() + alicePrivKey := alicePartner.MyRootPrivateKey() + bobPubKey := bobPartner.MyRootPrivateKey() grp := getGroup() aliceSIDHPrivKey, bobSIDHPubKey, _, _ := genSidhKeys() diff --git a/e2e/sendE2E.go b/e2e/sendE2E.go index 1a3c8b8850f98568d00316278b8e4e7b08de0d62..0dcd4acdc4977b2ef8c4e0c42d3d2cb9a22e438d 100644 --- a/e2e/sendE2E.go +++ b/e2e/sendE2E.go @@ -73,7 +73,7 @@ func (m *manager) sendE2E(mt catalog.MessageType, recipient *id.ID, return nil, e2e.MessageID{}, time.Time{}, err } - msgID := e2e.NewMessageID(partner.GetSendRelationshipFingerprint(), + msgID := e2e.NewMessageID(partner.SendRelationshipFingerprint(), internalMsgId) wg := sync.WaitGroup{} diff --git a/go.mod b/go.mod index 957e6ea2dd5991d7d82fbbcb4a505889bb4da15c..f10455acd0d08d2b1332403f8e99c3749651bbee 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/spf13/viper v1.7.1 gitlab.com/elixxir/bloomfilter v0.0.0-20200930191214-10e9ac31b228 gitlab.com/elixxir/comms v0.0.4-0.20220323190139-9ed75f3a8b2c - gitlab.com/elixxir/crypto v0.0.7-0.20220406193349-d25222ea3c6e + gitlab.com/elixxir/crypto v0.0.7-0.20220415172207-7de5e3cdb340 gitlab.com/elixxir/ekv v0.1.6 gitlab.com/elixxir/primitives v0.0.3-0.20220330212736-cce83b5f948f gitlab.com/xx_network/comms v0.0.4-0.20220315161313-76acb14429ac diff --git a/go.sum b/go.sum index 9b08ec215353ae39af5fc18f32821d63e6a88863..118b83d50d196d88162a2a23c234279b524f3fdc 100644 --- a/go.sum +++ b/go.sum @@ -283,6 +283,7 @@ gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp0 gitlab.com/elixxir/crypto v0.0.7-0.20220222221347-95c7ae58da6b/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= gitlab.com/elixxir/crypto v0.0.7-0.20220309234716-1ba339865787 h1:+qmsWov412+Yn7AKUhTbOcDgAydNXlNLPmFpO2W5LwY= gitlab.com/elixxir/crypto v0.0.7-0.20220309234716-1ba339865787/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= +gitlab.com/elixxir/crypto v0.0.7-0.20220317172048-3de167bd9406/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= gitlab.com/elixxir/crypto v0.0.7-0.20220325215559-7489d68d7714 h1:epnov8zyFWod14MUNtGHSbZCVSkZjN4NvoiBs1TgEV8= gitlab.com/elixxir/crypto v0.0.7-0.20220325215559-7489d68d7714/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= gitlab.com/elixxir/crypto v0.0.7-0.20220325224306-705ce59288bb h1:WdlmG+KPaM2Pjo1EFiFFPYEVSMV64Di1CitQnXGWBOQ= @@ -297,6 +298,12 @@ gitlab.com/elixxir/crypto v0.0.7-0.20220331001626-1829e71edf56 h1:1HJHlRwh3dDbvw gitlab.com/elixxir/crypto v0.0.7-0.20220331001626-1829e71edf56/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4= gitlab.com/elixxir/crypto v0.0.7-0.20220406193349-d25222ea3c6e h1:P+E0+AdevTNWBdqf4+covcmTrRfe6rKPLtevFrjbKQA= gitlab.com/elixxir/crypto v0.0.7-0.20220406193349-d25222ea3c6e/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4= +gitlab.com/elixxir/crypto v0.0.7-0.20220414175442-6d2304df43d7 h1:xEE795GeUyQaa4lRAI8IjyH31glm2OvFgzY9eiMEr1M= +gitlab.com/elixxir/crypto v0.0.7-0.20220414175442-6d2304df43d7/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4= +gitlab.com/elixxir/crypto v0.0.7-0.20220414225314-6f3eb9c073a5 h1:yw3G8ZEiWu2eSZWRQmj6nBhiJIYK3Cw2MJzDPkNHYVA= +gitlab.com/elixxir/crypto v0.0.7-0.20220414225314-6f3eb9c073a5/go.mod h1:tD6XjtQh87T2nKZL5I/pYPck5M2wLpkZ1Oz7H/LqO10= +gitlab.com/elixxir/crypto v0.0.7-0.20220415172207-7de5e3cdb340 h1:f1JsT60cKFXcHPoaOD1ohIOA22FQd42vbKjF9wrKfNs= +gitlab.com/elixxir/crypto v0.0.7-0.20220415172207-7de5e3cdb340/go.mod h1:JkByWX/TXCjdu6pRJsx+jwttbBGvlAljYSJMImDmt+4= gitlab.com/elixxir/ekv v0.1.6 h1:M2hUSNhH/ChxDd+s8xBqSEKgoPtmE6hOEBqQ73KbN6A= gitlab.com/elixxir/ekv v0.1.6/go.mod h1:e6WPUt97taFZe5PFLPb1Dupk7tqmDCTQu1kkstqJvw4= gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg= diff --git a/groupChat/makeGroup.go b/groupChat/makeGroup.go index cc0d22da3119d16a05b7f5dade00cc928ff1cf58..32be2b8318562da54cf0841cdda018aa411db58d 100644 --- a/groupChat/makeGroup.go +++ b/groupChat/makeGroup.go @@ -119,13 +119,13 @@ func (m Manager) buildMembership(members []*id.ID) (group.Membership, } contacts[i] = contact.Contact{ - ID: partner.GetPartnerID(), - DhPubKey: partner.GetPartnerOriginPublicKey(), + ID: partner.PartnerId(), + DhPubKey: partner.PartnerRootPublicKey(), } - dkl.Add(partner.GetMyOriginPrivateKey(), group.Member{ - ID: partner.GetPartnerID(), - DhKey: partner.GetPartnerOriginPublicKey(), + dkl.Add(partner.MyRootPrivateKey(), group.Member{ + ID: partner.PartnerId(), + DhKey: partner.PartnerRootPublicKey(), }, m.grp) } diff --git a/groupChat/manager_test.go b/groupChat/manager_test.go index 5a9c30cdc4db6e31d486bdd54a7a5243b846a30d..db891b387280540bf2d27b2a4f4c7e25da41d98e 100644 --- a/groupChat/manager_test.go +++ b/groupChat/manager_test.go @@ -150,8 +150,8 @@ func Test_newManager_LoadError(t *testing.T) { // m2, _ := newTestManagerWithStore(prng, 10, 0, requestFunc2, receiveFunc2, t) // m3, _ := newTestManagerWithStore(prng, 10, 0, requestFunc3, receiveFunc3, t) // -// membership, err := group.NewMembership(m1.store.GetUser().GetContact(), -// m2.store.GetUser().GetContact(), m3.store.GetUser().GetContact()) +// membership, err := group.NewMembership(m1.store.GetUser().Contact(), +// m2.store.GetUser().Contact(), m3.store.GetUser().Contact()) // if err != nil { // t.Errorf("Failed to generate new membership: %+v", err) // } diff --git a/groupChat/receiveRequest.go b/groupChat/receiveRequest.go index 3a8741d6b0a7e494c137ac53c6f1f7de9834a389..0d2224cbbcba375da4f440224c16b9d03e507eb5 100644 --- a/groupChat/receiveRequest.go +++ b/groupChat/receiveRequest.go @@ -85,10 +85,10 @@ func (m *Manager) readRequest(msg receive.Message) (gs.Group, error) { // Replace leader's public key with the one from the partnership leaderPubKey := membership[0].DhKey.DeepCopy() - membership[0].DhKey = partner.GetPartnerOriginPublicKey() + membership[0].DhKey = partner.PartnerRootPublicKey() // Generate the DH keys with each group member - privKey := partner.GetMyOriginPrivateKey() + privKey := partner.MyRootPrivateKey() dkl := gs.GenerateDhKeyList(m.receptionId, privKey, membership, m.grp) // Restore the original public key for the leader so that the membership diff --git a/single/cypher.go b/single/cypher.go index f4365ddc92d28d5035db88691707671f6a352a00..7a2925b52d3378cd6f1f56353196830957046515 100644 --- a/single/cypher.go +++ b/single/cypher.go @@ -19,37 +19,37 @@ import ( // makeCyphers generates all fingerprints for a given number of messages. func makeCyphers(dhKey *cyclic.Int, messageCount uint8) []cypher { - cylist := make([]cypher, messageCount) + cypherList := make([]cypher, messageCount) for i := uint8(0); i < messageCount; i++ { - cylist[i] = cypher{ - dhkey: dhKey, + cypherList[i] = cypher{ + dhKey: dhKey, num: i, } } - return cylist + return cypherList } type cypher struct { - dhkey *cyclic.Int + dhKey *cyclic.Int num uint8 } func (rk *cypher) getKey() []byte { - return singleUse.NewResponseKey(rk.dhkey, uint64(rk.num)) + return singleUse.NewResponseKey(rk.dhKey, uint64(rk.num)) } func (rk *cypher) GetFingerprint() format.Fingerprint { - return singleUse.NewResponseFingerprint(rk.dhkey, uint64(rk.num)) + return singleUse.NewResponseFingerprint(rk.dhKey, uint64(rk.num)) } func (rk *cypher) Encrypt(rp message.ResponsePart) ( fp format.Fingerprint, encryptedPayload, mac []byte) { fp = rk.GetFingerprint() key := rk.getKey() - //fixme: encryption is identical to what is used by e2e.Crypt, lets make - //them the same codepath + // FIXME: Encryption is identical to what is used by e2e.Crypt, lets make + // them the same code path. encryptedPayload = cAuth.Crypt(key, fp[:24], rp.Marshal()) mac = singleUse.MakeMAC(key, encryptedPayload) return fp, encryptedPayload, mac @@ -65,6 +65,6 @@ func (rk *cypher) Decrypt(contents, mac []byte) ([]byte, error) { return nil, errors.New("failed to verify the single use mac") } - //decrypt the payload + // Decrypt the payload return cAuth.Crypt(key, fp[:24], contents), nil } diff --git a/single/listener.go b/single/listener.go index d2f17233abbe1985a6e89cc73add5818108a262e..7be020b5e8812bc3dc5503659051935ab1a2c661 100644 --- a/single/listener.go +++ b/single/listener.go @@ -25,24 +25,24 @@ type Listener interface { type listener struct { myId *id.ID - myPrivkey *cyclic.Int + myPrivKey *cyclic.Int tag string grp *cyclic.Group cb Receiver net cmix.Client } -// Listen allows a server to listen for single use requests. It will register -// a service relative to the tag and myID as the identifier. Only a single -// listener can be active for a tag-myID pair, and error will return if that -// is violated. When requests are receved, they will be called on the +// Listen allows a server to listen for single use requests. It will register a +// service relative to the tag and myID as the identifier. Only a single +// listener can be active for a tag-myID pair, and an error will be returned if +// that is violated. When requests are received, they will be called on the // Receiver interface. -func Listen(tag string, myId *id.ID, privkey *cyclic.Int, net cmix.Client, +func Listen(tag string, myId *id.ID, privKey *cyclic.Int, net cmix.Client, e2eGrp *cyclic.Group, cb Receiver) Listener { l := &listener{ myId: myId, - myPrivkey: privkey, + myPrivKey: privKey, tag: tag, grp: e2eGrp, cb: cb, @@ -61,22 +61,20 @@ func Listen(tag string, myId *id.ID, privkey *cyclic.Int, net cmix.Client, } func (l *listener) Process(ecrMsg format.Message, - receptionID receptionID.EphemeralIdentity, - round rounds.Round) { + receptionID receptionID.EphemeralIdentity, round rounds.Round) { // Unmarshal the CMIX message contents to a transmission message transmitMsg, err := message.UnmarshalRequest(ecrMsg.GetContents(), l.grp.GetP().ByteLen()) if err != nil { - jww.WARN.Printf("failed to unmarshal contents on single use "+ + jww.WARN.Printf("Failed to unmarshal contents on single use "+ "request to %s on tag %s: %+v", l.myId, l.tag, err) return } // Generate DH key and symmetric key senderPubkey := transmitMsg.GetPubKey(l.grp) - dhKey := l.grp.Exp(senderPubkey, l.myPrivkey, - l.grp.NewInt(1)) + dhKey := l.grp.Exp(senderPubkey, l.myPrivKey, l.grp.NewInt(1)) key := singleUse.NewTransmitKey(dhKey) // Verify the MAC diff --git a/single/message/collator.go b/single/message/collator.go index 842d404ed8e223f4f25ec72a5b187b0cec1ee3cc..04ee11ab0e535bacc22ab4bb6f23a0e6c374e927 100644 --- a/single/message/collator.go +++ b/single/message/collator.go @@ -6,7 +6,7 @@ import ( "sync" ) -// Initial value of the Collator maxNum that indicates it has yet to be set +// Initial value of the Collator maxNum that indicates it has yet to be set. const unsetCollatorMax = -1 // Collator stores the list of payloads in the correct order. @@ -27,11 +27,11 @@ func NewCollator(messageCount uint8) *Collator { } // Collate collects message payload parts. Once all parts are received, the full -// collated payload is returned along with true. Otherwise returns false. +// collated payload is returned along with true. Otherwise, returns false. func (c *Collator) Collate(payloadBytes []byte) ([]byte, bool, error) { payload, err := UnmarshalResponse(payloadBytes) if err != nil { - return nil, false, errors.Errorf("Failed to unmarshal response "+ + return nil, false, errors.Errorf("failed to unmarshal response "+ "payload: %+v", err) } @@ -39,7 +39,7 @@ func (c *Collator) Collate(payloadBytes []byte) ([]byte, bool, error) { defer c.Unlock() // If this is the first message received, then set the max number of - // messages expected to be received off its max number of parts. + // messages expected to be received off its max number of parts if c.maxNum == unsetCollatorMax { if int(payload.GetNumParts()) > len(c.payloads) { return nil, false, errors.Errorf("Max number of parts reported by "+ diff --git a/single/message/collator_test.go b/single/message/collator_test.go index 6d7888326288ae2c0e0b5ff84da95416be179dbd..37be27c59669ad08082ac26fcbb2fc59f611c30c 100644 --- a/single/message/collator_test.go +++ b/single/message/collator_test.go @@ -18,7 +18,7 @@ func Test_newCollator(t *testing.T) { c := NewCollator(messageCount) if !reflect.DeepEqual(expected, c) { - t.Errorf("NewCollator() failed to generated the expected Collator."+ + t.Errorf("NewCollator failed to generate the expected Collator."+ "\nexepcted: %+v\nreceived: %+v", expected, c) } } @@ -51,20 +51,20 @@ func TestCollator_collate(t *testing.T) { fullPayload, collated, err = c.Collate(part.Marshal()) if err != nil { - t.Errorf("Collate() returned an error for part #%d: %+v", j, err) + t.Errorf("Collate returned an error for part #%d: %+v", j, err) } if i == messageCount && (!collated || fullPayload == nil) { - t.Errorf("Collate() failed to Collate a completed payload."+ + t.Errorf("Collate failed to collate a completed payload."+ "\ncollated: %v\nfullPayload: %+v", collated, fullPayload) } else if i < messageCount && (collated || fullPayload != nil) { - t.Errorf("Collate() signaled it collated an unfinished payload."+ + t.Errorf("Collate signaled it collated an unfinished payload."+ "\ncollated: %v\nfullPayload: %+v", collated, fullPayload) } } if !bytes.Equal(expectedData, fullPayload) { - t.Errorf("Collate() failed to return the correct collated data."+ + t.Errorf("Collate failed to return the correct collated data."+ "\nexpected: %s\nreceived: %s", expectedData, fullPayload) } } @@ -74,31 +74,35 @@ func TestCollator_collate_UnmarshalError(t *testing.T) { payloadBytes := []byte{1} c := NewCollator(1) payload, collated, err := c.Collate(payloadBytes) + expectedErr := "unmarshal" - if err == nil || !strings.Contains(err.Error(), "unmarshal") { - t.Errorf("Collate() failed to return an error for failing to "+ - "unmarshal the payload.\nerror: %+v", err) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("Collate failed to return an error for failing to "+ + "unmarshal the payload.\nexpected: %s\nreceived: %+v", + expectedErr, err) } if payload != nil || collated { - t.Errorf("Collate() signaled the payload was collated on error."+ + t.Errorf("Collate signaled the payload was collated on error."+ "\npayload: %+v\ncollated: %+v", payload, collated) } } -// Error path: max reported parts by payload larger then set in Collator +// Error path: max reported parts by payload larger than set in Collator. func TestCollator_collate_MaxPartsError(t *testing.T) { payloadBytes := []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF} c := NewCollator(1) payload, collated, err := c.Collate(payloadBytes) + expectedErr := "Max number of parts" - if err == nil || !strings.Contains(err.Error(), "Max number of parts") { - t.Errorf("Collate() failed to return an error when the max number of "+ - "parts is larger than the payload size.\nerror: %+v", err) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("Collate failed to return an error when the max number of "+ + "parts is larger than the payload size."+ + "\nexpected: %s\nreceived: %+v", expectedErr, err) } if payload != nil || collated { - t.Errorf("Collate() signaled the payload was collated on error."+ + t.Errorf("Collate signaled the payload was collated on error."+ "\npayload: %+v\ncollated: %+v", payload, collated) } } @@ -107,16 +111,13 @@ func TestCollator_collate_MaxPartsError(t *testing.T) { func TestCollator_collate_PartNumTooLargeError(t *testing.T) { payloadBytes := []byte{25, 5, 5, 5, 5} c := NewCollator(5) - payload, collated, err := c.Collate(payloadBytes) - - if err == nil || !strings.Contains(err.Error(), "greater than max number of expected parts") { - t.Errorf("Collate() failed to return an error when the part number is "+ - "greater than the max number of parts.\nerror: %+v", err) - } + _, _, err := c.Collate(payloadBytes) + expectedErr := "greater than max number of expected parts" - if payload != nil || collated { - t.Errorf("Collate() signaled the payload was collated on error."+ - "\npayload: %+v\ncollated: %+v", payload, collated) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("Collate failed to return the expected error when the part "+ + "number is greater than the max number of parts."+ + "\nexpected: %s\nreceived: %+v", expectedErr, err) } } @@ -124,19 +125,15 @@ func TestCollator_collate_PartNumTooLargeError(t *testing.T) { func TestCollator_collate_PartExistsError(t *testing.T) { payloadBytes := []byte{0, 1, 5, 0, 1, 20} c := NewCollator(5) - payload, collated, err := c.Collate(payloadBytes) + _, _, err := c.Collate(payloadBytes) if err != nil { - t.Fatalf("Collate() returned an error: %+v", err) - } - - payload, collated, err = c.Collate(payloadBytes) - if err == nil || !strings.Contains(err.Error(), "A payload for the part number") { - t.Errorf("Collate() failed to return an error when the part number "+ - "already exists.\nerror: %+v", err) + t.Fatalf("Collate returned an error: %+v", err) } + expectedErr := "A payload for the part number" - if payload != nil || collated { - t.Errorf("Collate() signaled the payload was collated on error."+ - "\npayload: %+v\ncollated: %+v", payload, collated) + _, _, err = c.Collate(payloadBytes) + if err == nil || !strings.Contains(err.Error(), expectedErr) { + t.Errorf("Collate failed to return an error when the part number "+ + "already exists.\nexpected: %s\nreceived: %+v", expectedErr, err) } } diff --git a/single/message/request.go b/single/message/request.go index 60f372e8b3aa8deab89a315cd2f32b5d0e2044bd..d2b0280446998f67017823b9903051ba79974eb7 100644 --- a/single/message/request.go +++ b/single/message/request.go @@ -19,15 +19,15 @@ import ( ) /* -+------------------------------------------------------------------------------+ -| CMIX Message Contents | -+------------+-------------------------------------------- --------+ -| Version | pubKey | payload (RequestPayload) | -| 1 byte | pubKeySize | externalPayloadSize - pubKeySize | -+------------+------------+----------+---------+----------+---------+----------+ - | Tag FP | nonce | maxResponseParts | size | contents | - | 16 bytes | 8 bytes | 1 byte | 2 bytes | variable | - +----------+---------+----------+---------+----------+ ++-------------------------------------------------------------------------------------+ +| CMIX Message Contents | ++-----------+------------+------------------------------------------------------------+ +| Version | pubKey | payload (RequestPayload) | +| 1 byte | pubKeySize | externalPayloadSize - pubKeySize | ++-----------+------------+----------+---------+------------------+---------+----------+ + | Tag FP | nonce | maxResponseParts | size | contents | + | 16 bytes | 8 bytes | 1 byte | 2 bytes | variable | + +----------+---------+------------------+---------+----------+ */ const transmitMessageVersion = 0 @@ -138,9 +138,9 @@ const ( // RequestPayload is the structure of Request's payload. type RequestPayload struct { - data []byte // Serial of all contents e + data []byte // Serial of all contents nonce []byte - numRequestParts []byte //number fo parts in the request, currently always 1 + numRequestParts []byte // Number of parts in the request, currently always 1 maxResponseParts []byte // Max number of messages expected in response size []byte // Size of the contents contents []byte @@ -207,7 +207,7 @@ func (mp RequestPayload) GetRID(pubKey *cyclic.Int) *id.ID { return singleUse.NewRecipientID(pubKey, mp.Marshal()) } -// GetNonce returns the nonce as a uint64. +// GetNonce returns the nonce as an uint64. func (mp RequestPayload) GetNonce() uint64 { return binary.BigEndian.Uint64(mp.nonce) } diff --git a/single/message/request_test.go b/single/message/request_test.go index 0e4cd087855550ba691e67edf8fbe82638d5ed81..2e577729ce9fe23263dd508f83b692bf37104229 100644 --- a/single/message/request_test.go +++ b/single/message/request_test.go @@ -35,7 +35,7 @@ func Test_newTransmitMessage(t *testing.T) { m := NewRequest(externalPayloadSize, pubKeySize) if !reflect.DeepEqual(expected, m) { - t.Errorf("NewRequest() did not produce the expected Request."+ + t.Errorf("NewRequest did not produce the expected Request."+ "\nexpected: %#v\nreceived: %#v", expected, m) } } @@ -44,7 +44,7 @@ func Test_newTransmitMessage(t *testing.T) { func Test_newTransmitMessage_PubKeySizeError(t *testing.T) { defer func() { if r := recover(); r == nil || !strings.Contains(r.(string), "Payload size") { - t.Error("NewRequest() did not panic when the size of " + + t.Error("NewRequest did not panic when the size of " + "the payload is smaller than the size of the public key.") } }() @@ -69,17 +69,17 @@ func Test_mapTransmitMessage(t *testing.T) { m := mapRequest(data, pubKeySize) if !bytes.Equal(data, m.data) { - t.Errorf("mapRequest() failed to map the correct bytes for data."+ + t.Errorf("mapRequest failed to map the correct bytes for data."+ "\nexpected: %+v\nreceived: %+v", data, m.data) } if !bytes.Equal(pubKey, m.pubKey) { - t.Errorf("mapRequest() failed to map the correct bytes for pubKey."+ + t.Errorf("mapRequest failed to map the correct bytes for pubKey."+ "\nexpected: %+v\nreceived: %+v", pubKey, m.pubKey) } if !bytes.Equal(payload, m.payload) { - t.Errorf("mapRequest() failed to map the correct bytes for payload."+ + t.Errorf("mapRequest failed to map the correct bytes for payload."+ "\nexpected: %+v\nreceived: %+v", payload, m.payload) } } @@ -110,7 +110,7 @@ func TestTransmitMessage_Marshal_Unmarshal(t *testing.T) { func Test_unmarshalTransmitMessage_PubKeySizeError(t *testing.T) { _, err := UnmarshalRequest([]byte{1, 2, 3}, 5) if err == nil { - t.Error("unmarshalRequest() did not produce an error when the " + + t.Error("unmarshalRequest did not produce an error when the " + "byte slice is smaller than the public key size.") } } @@ -126,12 +126,12 @@ func TestTransmitMessage_SetPubKey_GetPubKey_GetPubKeySize(t *testing.T) { testPubKey := m.GetPubKey(grp) if pubKey.Cmp(testPubKey) != 0 { - t.Errorf("GetPubKey() failed to get correct public key."+ + t.Errorf("GetPubKey failed to get correct public key."+ "\nexpected: %s\nreceived: %s", pubKey.Text(10), testPubKey.Text(10)) } if pubKeySize != m.GetPubKeySize() { - t.Errorf("GetPubKeySize() failed to return the correct size."+ + t.Errorf("GetPubKeySize failed to return the correct size."+ "\nexpected: %d\nreceived: %d", pubKeySize, m.GetPubKeySize()) } } @@ -149,22 +149,25 @@ func TestTransmitMessage_SetPayload_GetPayload_GetPayloadSize(t *testing.T) { testPayload := m.GetPayload() if !bytes.Equal(payload, testPayload) { - t.Errorf("GetContents() returned incorrect payload."+ + t.Errorf("GetContents returned incorrect payload."+ "\nexpected: %+v\nreceived: %+v", payload, testPayload) } if payloadSize != m.GetPayloadSize() { - t.Errorf("GetContentsSize() returned incorrect content size."+ + t.Errorf("GetContentsSize returned incorrect content size."+ "\nexpected: %d\nreceived: %d", payloadSize, m.GetPayloadSize()) } } // Error path: supplied payload is not the same size as message payload. func TestTransmitMessage_SetPayload_PayloadSizeError(t *testing.T) { + expectedErr := "is not the same as the size" defer func() { - if r := recover(); r == nil || !strings.Contains(r.(string), "is not the same as the size") { - t.Error("SetContents() did not panic when the size of supplied " + - "contents is not the same size as message contents.") + if r := recover(); r == nil || !strings.Contains(r.(string), expectedErr) { + t.Errorf("SetContents did not panic with the expected error when "+ + "the size of supplied contents is not the same size as "+ + "message contents.\nexpected: %s\nreceived: %+v", + expectedErr, r) } }() @@ -187,24 +190,29 @@ func Test_newTransmitMessagePayload(t *testing.T) { expected.numRequestParts[0] = 1 binary.BigEndian.PutUint16(expected.size, uint16(payloadSize-transmitPlMinSize)) expected.SetMaxResponseParts(10) - expected.data = append(expected.nonce, append(expected.numRequestParts, append(expected.maxResponseParts, append(expected.size, expected.contents...)...)...)...) + expected.data = append(expected.nonce, + append(expected.numRequestParts, + append(expected.maxResponseParts, + append(expected.size, expected.contents...)...)...)...) payload := make([]byte, payloadSize-transmitPlMinSize) mp := NewRequestPayload(payloadSize, payload, 10) if !reflect.DeepEqual(expected, mp) { - t.Errorf("NewRequestPayload() did not produce the expected "+ + t.Errorf("NewRequestPayload did not produce the expected "+ "RequestPayload.\nexpected: %+v\nreceived: %+v", expected, mp) } } -// Error path: payload size is smaller than than rid size + maxResponseParts size. +// Error path: payload size is smaller than rid size + maxResponseParts size. func Test_newTransmitMessagePayload_PayloadSizeError(t *testing.T) { + expectedErr := "Size of single-use transmission message payload" defer func() { - if r := recover(); r == nil || !strings.Contains(r.(string), "Size of single-use transmission message payload") { - t.Error("NewRequestPayload() did not panic when the size " + - "of the payload is smaller than the size of the reception ID " + - "+ the message count.") + if r := recover(); r == nil || !strings.Contains(r.(string), expectedErr) { + t.Errorf("NewRequestPayload did not panic with the expected error "+ + "when the size of the payload is smaller than the size of the "+ + "reception ID + the message count.\nexpected: %s\nreceived: %+v", + expectedErr, r) } }() payloadSize := 10 @@ -237,17 +245,17 @@ func Test_mapTransmitMessagePayload(t *testing.T) { mp := mapRequestPayload(data) if !bytes.Equal(data, mp.data) { - t.Errorf("mapRequestPayload() failed to map the correct bytes "+ + t.Errorf("mapRequestPayload failed to map the correct bytes "+ "for data.\nexpected: %+v\nreceived: %+v", data, mp.data) } if !bytes.Equal(nonceBytes, mp.nonce) { - t.Errorf("mapRequestPayload() failed to map the correct bytes "+ + t.Errorf("mapRequestPayload failed to map the correct bytes "+ "for the nonce.\nexpected: %s\nreceived: %s", nonceBytes, mp.nonce) } if !bytes.Equal(numRequestParts, mp.numRequestParts) { - t.Errorf("mapRequestPayload() failed to map the correct bytes "+ + t.Errorf("mapRequestPayload failed to map the correct bytes "+ "for the numRequestParts.\nexpected: %s\nreceived: %s", nonceBytes, mp.nonce) } @@ -256,12 +264,12 @@ func Test_mapTransmitMessagePayload(t *testing.T) { } if !bytes.Equal(size, mp.size) { - t.Errorf("mapRequestPayload() failed to map the correct bytes "+ + t.Errorf("mapRequestPayload failed to map the correct bytes "+ "for size.\nexpected: %+v\nreceived: %+v", size, mp.size) } if !bytes.Equal(contents, mp.contents) { - t.Errorf("mapRequestPayload() failed to map the correct bytes "+ + t.Errorf("mapRequestPayload failed to map the correct bytes "+ "for contents.\nexpected: %+v\nreceived: %+v", contents, mp.contents) } } @@ -277,7 +285,7 @@ func TestTransmitMessagePayload_Marshal_Unmarshal(t *testing.T) { testPayload, err := UnmarshalRequestPayload(payloadBytes) if err != nil { - t.Errorf("UnmarshalRequestPayload() produced an error: %+v", err) + t.Errorf("UnmarshalRequestPayload produced an error: %+v", err) } if !reflect.DeepEqual(mp, testPayload) { @@ -290,7 +298,7 @@ func TestTransmitMessagePayload_Marshal_Unmarshal(t *testing.T) { func Test_unmarshalTransmitMessagePayload(t *testing.T) { _, err := UnmarshalRequestPayload([]byte{6}) if err == nil { - t.Error("UnmarshalRequestPayload() did not return an error " + + t.Error("UnmarshalRequestPayload did not return an error " + "when the supplied byte slice was too small.") } } @@ -311,7 +319,7 @@ func TestTransmitMessagePayload_GetRID(t *testing.T) { testRID := mp.GetRID(getGroup().NewInt(42)) if !expectedRID.Cmp(testRID) { - t.Errorf("GetRID() did not return the expected ID."+ + t.Errorf("GetRID did not return the expected ID."+ "\nexpected: %s\nreceived: %s", expectedRID, testRID) } } @@ -333,11 +341,11 @@ func Test_transmitMessagePayload_SetNonce_GetNonce(t *testing.T) { binary.BigEndian.PutUint64(expectedNonceBytes, expectedNonce) err = mp.SetNonce(strings.NewReader(string(expectedNonceBytes))) if err != nil { - t.Errorf("SetNonce() produced an error: %+v", err) + t.Errorf("SetNonce produced an error: %+v", err) } if expectedNonce != mp.GetNonce() { - t.Errorf("GetNonce() did not return the expected nonce."+ + t.Errorf("GetNonce did not return the expected nonce."+ "\nexpected: %d\nreceived: %d", expectedNonce, mp.GetNonce()) } } @@ -356,7 +364,7 @@ func Test_transmitMessagePayload_SetNonce_RngError(t *testing.T) { err = mp.SetNonce(strings.NewReader("")) if !check(err, "failed to generate nonce") { - t.Errorf("SetNonce() did not return an error when nonce generation "+ + t.Errorf("SetNonce did not return an error when nonce generation "+ "fails: %+v", err) } } @@ -378,7 +386,7 @@ func TestTransmitMessagePayload_SetMaxParts_GetMaxParts(t *testing.T) { testCount := mp.GetMaxResponseParts() if count != testCount { - t.Errorf("GetNumParts() did not return the expected count."+ + t.Errorf("GetNumParts did not return the expected count."+ "\nexpected: %d\nreceived: %d", count, testCount) } } @@ -395,27 +403,31 @@ func TestTransmitMessagePayload_SetContents_GetContents_GetContentsSize_GetMaxCo testContents := mp.GetContents() if !bytes.Equal(contents, testContents) { - t.Errorf("GetContents() did not return the expected contents."+ + t.Errorf("GetContents did not return the expected contents."+ "\nexpected: %+v\nreceived: %+v", contents, testContents) } if contentsSize != mp.GetContentsSize() { - t.Errorf("GetContentsSize() did not return the expected size."+ + t.Errorf("GetContentsSize did not return the expected size."+ "\nexpected: %d\nreceived: %d", contentsSize, mp.GetContentsSize()) } if format.MinimumPrimeSize-transmitPlMinSize != mp.GetMaxContentsSize() { - t.Errorf("GetMaxContentsSize() did not return the expected size."+ - "\nexpected: %d\nreceived: %d", format.MinimumPrimeSize-transmitPlMinSize, mp.GetMaxContentsSize()) + t.Errorf("GetMaxContentsSize did not return the expected size."+ + "\nexpected: %d\nreceived: %d", + format.MinimumPrimeSize-transmitPlMinSize, mp.GetMaxContentsSize()) } } // Error path: supplied bytes are smaller than payload contents. func TestTransmitMessagePayload_SetContents(t *testing.T) { + expectedErr := "max size of message content" defer func() { - if r := recover(); r == nil || !strings.Contains(r.(string), "max size of message content") { - t.Error("SetContents() did not panic when the size of the " + - "supplied bytes is not the same as the payload content size.") + if r := recover(); r == nil || !strings.Contains(r.(string), expectedErr) { + t.Errorf("SetContents did not panic with the expected error when "+ + "the size of the supplied bytes is not the same as the "+ + "payload content size.\nexpected: %s\nreceived: %+v", + expectedErr, r) } }() diff --git a/single/message/response.go b/single/message/response.go index 2fde98e94019e538b4fbf638d143079a363ecaae..55651e50d6f2d08e9b920d149563e6d30651201c 100644 --- a/single/message/response.go +++ b/single/message/response.go @@ -22,12 +22,12 @@ const ( ) /* -+---------------------------------------------------+ -| CMIX Message Contents | -+---------+----------+---------+---------+----------+ ++-----------------------------------------------------------+ +| CMIX Message Contents | ++---------+------------------+---------+---------+----------+ | version | maxResponseParts | size | partNum | contents | -| 1 bytes | 1 byte | 2 bytes | 1 bytes | variable | -+------------+----------+---------+------+----------+ +| 1 bytes | 1 byte | 2 bytes | 1 bytes | variable | ++---------+------------------+---------+---------+----------+ */ type ResponsePart struct { @@ -39,8 +39,7 @@ type ResponsePart struct { contents []byte // The encrypted contents } -// NewResponsePart generates a new response message part of the specified -// size. +// NewResponsePart generates a new response message part of the specified size. func NewResponsePart(externalPayloadSize int) ResponsePart { if externalPayloadSize < responseMinSize { jww.FATAL.Panicf("Failed to create new single-use response message "+ diff --git a/single/message/response_test.go b/single/message/response_test.go index 4d4e85fcb2c6bae21f48c85c6059615f6a65c969..13f1c1e2367476795a747de2398a23e4e7c67c9e 100644 --- a/single/message/response_test.go +++ b/single/message/response_test.go @@ -31,17 +31,19 @@ func Test_newResponseMessagePart(t *testing.T) { rmp := NewResponsePart(payloadSize) if !reflect.DeepEqual(expected, rmp) { - t.Errorf("NewResponsePart() did not return the expected "+ + t.Errorf("NewResponsePart did not return the expected "+ "ResponsePart.\nexpected: %+v\nreceived: %+v", expected, rmp) } } // Error path: provided contents size is not large enough. func Test_newResponseMessagePart_PayloadSizeError(t *testing.T) { + expectedErr := "size of external payload" defer func() { - if r := recover(); r == nil || !strings.Contains(r.(string), "size of external payload") { - t.Error("NewResponsePart() did not panic when the size of " + - "the payload is smaller than the required size.") + if r := recover(); r == nil || !strings.Contains(r.(string), expectedErr) { + t.Errorf("NewResponsePart did not panic with the expected error "+ + "when the size of the payload is smaller than the required "+ + "size.\nexpected: %s\nreceived: %+v", expectedErr, r) } }() @@ -65,22 +67,22 @@ func Test_mapResponseMessagePart(t *testing.T) { rmp := mapResponsePart(data) if expectedPartNum != rmp.partNum[0] { - t.Errorf("mapResponsePart() did not correctly map partNum."+ + t.Errorf("mapResponsePart did not correctly map partNum."+ "\nexpected: %d\nreceived: %d", expectedPartNum, rmp.partNum[0]) } if expectedMaxParts != rmp.maxParts[0] { - t.Errorf("mapResponsePart() did not correctly map maxResponseParts."+ + t.Errorf("mapResponsePart did not correctly map maxResponseParts."+ "\nexpected: %d\nreceived: %d", expectedMaxParts, rmp.maxParts[0]) } if !bytes.Equal(expectedContents, rmp.contents) { - t.Errorf("mapResponsePart() did not correctly map contents."+ + t.Errorf("mapResponsePart did not correctly map contents."+ "\nexpected: %+v\nreceived: %+v", expectedContents, rmp.contents) } if !bytes.Equal(data, rmp.data) { - t.Errorf("mapResponsePart() did not save the data correctly."+ + t.Errorf("mapResponsePart did not save the data correctly."+ "\nexpected: %+v\nreceived: %+v", data, rmp.data) } } @@ -96,11 +98,11 @@ func TestResponseMessagePart_Marshal_Unmarshal(t *testing.T) { newRmp, err := UnmarshalResponse(data) if err != nil { - t.Errorf("UnmarshalResponse() produced an error: %+v", err) + t.Errorf("UnmarshalResponse produced an error: %+v", err) } if !reflect.DeepEqual(rmp, newRmp) { - t.Errorf("Failed to Marshal() and unmarshal() the ResponsePart."+ + t.Errorf("Failed to Marshal and unmarshal the ResponsePart."+ "\nexpected: %+v\nrecieved: %+v", rmp, newRmp) } } @@ -109,7 +111,7 @@ func TestResponseMessagePart_Marshal_Unmarshal(t *testing.T) { func Test_unmarshalResponseMessage(t *testing.T) { _, err := UnmarshalResponse([]byte{1}) if err == nil { - t.Error("UnmarshalResponse() did not produce an error when the " + + t.Error("UnmarshalResponse did not produce an error when the " + "byte slice is smaller required.") } } @@ -123,7 +125,7 @@ func TestResponseMessagePart_SetPartNum_GetPartNum(t *testing.T) { rmp.SetPartNum(expectedPartNum) if expectedPartNum != rmp.GetPartNum() { - t.Errorf("GetPartNum() failed to return the expected part number."+ + t.Errorf("GetPartNum failed to return the expected part number."+ "\nexpected: %d\nrecieved: %d", expectedPartNum, rmp.GetPartNum()) } } @@ -137,7 +139,7 @@ func TestResponseMessagePart_SetMaxParts_GetMaxParts(t *testing.T) { rmp.SetNumParts(expectedMaxParts) if expectedMaxParts != rmp.GetNumParts() { - t.Errorf("GetNumParts() failed to return the expected max parts."+ + t.Errorf("GetNumParts failed to return the expected max parts."+ "\nexpected: %d\nrecieved: %d", expectedMaxParts, rmp.GetNumParts()) } } @@ -153,28 +155,30 @@ func TestResponseMessagePart_SetContents_GetContents_GetContentsSize_GetMaxConte rmp.SetContents(expectedContents) if !bytes.Equal(expectedContents, rmp.GetContents()) { - t.Errorf("GetContents() failed to return the expected contents."+ + t.Errorf("GetContents failed to return the expected contents."+ "\nexpected: %+v\nrecieved: %+v", expectedContents, rmp.GetContents()) } if contentSize != rmp.GetContentsSize() { - t.Errorf("GetContentsSize() failed to return the expected contents size."+ + t.Errorf("GetContentsSize failed to return the expected contents size."+ "\nexpected: %d\nrecieved: %d", contentSize, rmp.GetContentsSize()) } if externalPayloadSize-responseMinSize != rmp.GetMaxContentsSize() { - t.Errorf("GetMaxContentsSize() failed to return the expected max contents size."+ - "\nexpected: %d\nrecieved: %d", + t.Errorf("GetMaxContentsSize failed to return the expected max "+ + "contents size.\nexpected: %d\nrecieved: %d", externalPayloadSize-responseMinSize, rmp.GetMaxContentsSize()) } } // Error path: size of supplied contents does not match message contents size. func TestResponseMessagePart_SetContents_ContentsSizeError(t *testing.T) { + expectedErr := "max size of message contents" defer func() { - if r := recover(); r == nil || !strings.Contains(r.(string), "max size of message contents") { - t.Error("SetContents() did not panic when the size of the supplied " + - "bytes is larger than the content size.") + if r := recover(); r == nil || !strings.Contains(r.(string), expectedErr) { + t.Errorf("SetContents did not panic with the expected error when "+ + "the size of the supplied bytes is larger than the content "+ + "size.\nexpected: %s\nreceived: %+v", expectedErr, r) } }() diff --git a/single/receivedRequest.go b/single/receivedRequest.go index c425cc9dd2da4dd4f45d89b678778041d7a463d9..7de42ddcea880386e36d2590688c95bb1f58d6b6 100644 --- a/single/receivedRequest.go +++ b/single/receivedRequest.go @@ -67,9 +67,9 @@ func (r Request) String() string { } // Respond is used to respond to the request. It sends a payload up to -// r.GetMaxResponseLength(). It will chunk the message into multiple -// cmix messages if it is too long for a single message. It will fail -// If a single cmix message cannot be sent. +// Request.GetMaxResponseLength. It will chunk the message into multiple cMix +// messages if it is too long for a single message. It will fail if a single +// cMix message cannot be sent. func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, timeout time.Duration) ([]id.Round, error) { // make sure this has only been run once @@ -79,7 +79,7 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, "single-use response that has already been responded to.") } - //check that the payload isn't too long + // Check that the payload is not too long if len(payload) > r.GetMaxResponseLength() { return nil, errors.Errorf("length of provided "+ "payload too long for message payload capacity, max: %d, "+ @@ -87,10 +87,10 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, len(payload)) } - //partition the payload + // Partition the payload parts := partitionResponse(payload, r.net.GetMaxMessageLength(), r.maxParts) - //encrypt and send the partitions + // Encrypt and send the partitions cyphers := makeCyphers(r.dhKey, uint8(len(parts))) rounds := make([]id.Round, len(parts)) sendResults := make(chan ds.EventReturn, len(parts)) @@ -104,7 +104,7 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, svc := cmixMsg.Service{ Identifier: r.dhKey.Bytes(), - Tag: "single.response-dummyservice", + Tag: "single.response-dummyService", Metadata: nil, } @@ -136,7 +136,7 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, if failed > 0 { return nil, errors.Errorf("One or more send failed for the " + - "response, the response will be handleable and will timeout") + "response, the response will be handleable and will time out") } jww.DEBUG.Printf("Sent %d single-use response CMIX messages to %s.", @@ -151,7 +151,8 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, } // Wait until the result tracking responds - success, numRoundFail, numTimeOut := cmix.TrackResults(sendResults, len(roundMap)) + success, numRoundFail, numTimeOut := cmix.TrackResults( + sendResults, len(roundMap)) if !success { return nil, errors.Errorf("tracking results of %d rounds: %d round "+ @@ -159,12 +160,13 @@ func (r Request) Respond(payload []byte, cmixParams cmix.CMIXParams, len(rounds), numRoundFail, numTimeOut) } - jww.DEBUG.Printf("Tracked %d single-use response message round(s).", len(roundMap)) + jww.DEBUG.Printf("Tracked %d single-use response message round(s).", + len(roundMap)) return rounds, nil } -// partitionResponse breaks a payload into its sub payloads for sending +// partitionResponse breaks a payload into its sub payloads for sending. func partitionResponse(payload []byte, cmixMessageLength int, maxParts uint8) []message.ResponsePart { responseMsg := message.NewResponsePart(cmixMessageLength) diff --git a/single/request.go b/single/request.go index cd8a5c04a27857730205bccdc7633238bf3264d0..0db4f433469e5e5a4b8b5358da8de139b8c3a130 100644 --- a/single/request.go +++ b/single/request.go @@ -41,33 +41,31 @@ func GetDefaultRequestParams() RequestParams { } } -// GetMaxRequestSize returns the max size of a request payload +// GetMaxRequestSize returns the max size of a request payload. func GetMaxRequestSize(net cmix.Client, e2eGrp *cyclic.Group) uint { payloadSize := message.GetRequestPayloadSize(net.GetMaxMessageLength(), e2eGrp.GetP().ByteLen()) return message.GetRequestContentsSize(payloadSize) } -/* Single is a system which allows for an end to end encrypted anonymous - request to be sent to another cmix client, and for them to respond. The - system allows for communication over the mixnet without an interactive - key negotiation because the payload inherently carries the negotiation with - it. When sending a new request, a client create a new discreet log Dh keypair - as well as a new ID. As a result of the fact that the client never - identifies itself, the system allows the client to stay anonymous while - contacting the remote. +/* Single is a system which allows for an end-to-end encrypted anonymous request + to be sent to another cMix client, and for them to respond. The system allows + for communication over the mixnet without an interactive key negotiation + because the payload inherently carries the negotiation with it. When sending + a new request, a client create a new discreet log DH keypair as well as a new + ID. As a result of the fact that the client never identifies itself, the + system allows the client to stay anonymous while contacting the remote. */ -// TransmitRequest Sends a request to the recipient with the given tag containing -// the given payload. The request is identified as coming from a new user ID and -// the recipient of the request responds to that address. As a result, this request -// does not reveal the identity of the sender, -// the current implementation only allows for a cing cmix request payload. +// TransmitRequest sends a request to the recipient with the given tag +// containing the given payload. The request is identified as coming from a new +// user ID and the recipient of the request responds to that address. As a +// result, this request does not reveal the identity of the sender. +// The current implementation only allows for a single cMix request payload. // Because the request payload itself must include negotiation materials, it is // limited to just a few thousand bits of payload, and will return an error if -// the payload is too large. GetMaxRequestSize() can be used to get this max -// size -// The network follower must be running and healthy to transmit +// the payload is too large. GetMaxRequestSize can be used to get this max size. +// The network follower must be running and healthy to transmit. func TransmitRequest(recipient contact.Contact, tag string, payload []byte, callback Response, param RequestParams, net cmix.Client, rng csprng.Source, e2eGrp *cyclic.Group) (id.Round, receptionID.EphemeralIdentity, error) { @@ -76,7 +74,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, "send singe use when network is not healthy") } - // get address ID address space size; this blocks until the address space + // Get address ID address space size; this blocks until the address space // size is set for the first time addressSize := net.GetAddressSpace() timeStart := netTime.Now() @@ -87,18 +85,19 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, return 0, receptionID.EphemeralIdentity{}, err } - //build the message payload - request := message.NewRequest(net.GetMaxMessageLength(), - e2eGrp.GetP().ByteLen()) - requestPayload := message.NewRequestPayload(request.GetPayloadSize(), - payload, param.MaxResponseMessages) + // Build the message payload + request := message.NewRequest( + net.GetMaxMessageLength(), e2eGrp.GetP().ByteLen()) + requestPayload := message.NewRequestPayload( + request.GetPayloadSize(), payload, param.MaxResponseMessages) // Generate new user ID and address ID var sendingID receptionID.EphemeralIdentity - requestPayload, sendingID, err = makeIDs(requestPayload, publicKey, addressSize, param.Timeout, - timeStart, rng) + requestPayload, sendingID, err = makeIDs( + requestPayload, publicKey, addressSize, param.Timeout, timeStart, rng) if err != nil { - return 0, receptionID.EphemeralIdentity{}, errors.Errorf("failed to generate IDs: %+v", err) + return 0, receptionID.EphemeralIdentity{}, + errors.Errorf("failed to generate IDs: %+v", err) } // Encrypt payload @@ -109,11 +108,11 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, // Generate CMIX message MAC mac := singleUse.MakeMAC(key, encryptedPayload) - //assemble the payload + // Assemble the payload request.SetPubKey(publicKey) request.SetPayload(encryptedPayload) - //register the response pickup + // Register the response pickup collator := message.NewCollator(param.MaxResponseMessages) timeoutKillChan := make(chan bool) callbackOnce := sync.Once{} @@ -123,6 +122,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, case timeoutKillChan <- true: default: } + callbackOnce.Do(func() { net.DeleteClientFingerprints(sendingID.Source) go callback.Callback(payload, receptionID, round, err) @@ -132,7 +132,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, cyphers := makeCyphers(dhKey, param.MaxResponseMessages) for i := uint8(0); i < param.MaxResponseMessages; i++ { - processor := responceProcessor{ + processor := responseProcessor{ sendingID: sendingID, c: collator, callback: wrapper, @@ -141,8 +141,9 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, recipient: &recipient, } - if err = net.AddFingerprint(sendingID.Source, processor.cy.GetFingerprint(), - &processor); err != nil { + err = net.AddFingerprint( + sendingID.Source, processor.cy.GetFingerprint(), &processor) + if err != nil { return 0, receptionID.EphemeralIdentity{}, errors.Errorf("failed to add fingerprint %d IDs: %+v", i, err) } @@ -150,7 +151,7 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, net.AddIdentity(sendingID.Source, timeStart.Add(param.Timeout), false) - //send the payload + // Send the payload svc := cmixMsg.Service{ Identifier: recipient.ID[:], Tag: tag, @@ -158,8 +159,8 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, } param.CmixParam.Timeout = param.Timeout - rid, _, err := net.Send(recipient.ID, cmixMsg.RandomFingerprint(rng), svc, request.Marshal(), mac, - param.CmixParam) + rid, _, err := net.Send(recipient.ID, cmixMsg.RandomFingerprint(rng), svc, + request.Marshal(), mac, param.CmixParam) if err != nil { return 0, receptionID.EphemeralIdentity{}, err @@ -175,8 +176,8 @@ func TransmitRequest(recipient contact.Contact, tag string, payload []byte, func generateDhKeys(grp *cyclic.Group, dhPubKey *cyclic.Int, rng io.Reader) (*cyclic.Int, *cyclic.Int, error) { // Generate private key - privKeyBytes, err := csprng.GenerateInGroup(grp.GetP().Bytes(), - grp.GetP().ByteLen(), rng) + privKeyBytes, err := csprng.GenerateInGroup( + grp.GetP().Bytes(), grp.GetP().ByteLen(), rng) if err != nil { return nil, nil, errors.Errorf("failed to generate key in group: %+v", err) @@ -191,12 +192,12 @@ func generateDhKeys(grp *cyclic.Group, dhPubKey *cyclic.Int, // makeIDs generates a new user ID and address ID with a start and end within // the given timout. The ID is generated from the unencrypted msg payload, which -// contains a nonce. If the generated address ID has a window that is not -// within +/- the given 2*Timeout from now, then the IDs are generated again -// using a new nonce. +// contains a nonce. If the generated address ID has a window that is not within +// +/- the given 2*Timeout from now, then the IDs are generated again using a +// new nonce. func makeIDs(msg message.RequestPayload, publicKey *cyclic.Int, - addressSize uint8, timeout time.Duration, timeNow time.Time, - rng io.Reader) (message.RequestPayload, receptionID.EphemeralIdentity, error) { + addressSize uint8, timeout time.Duration, timeNow time.Time, rng io.Reader) ( + message.RequestPayload, receptionID.EphemeralIdentity, error) { var rid *id.ID var ephID ephemeral.Id @@ -217,19 +218,20 @@ func makeIDs(msg message.RequestPayload, publicKey *cyclic.Int, rid = msg.GetRID(publicKey) // Generate the address ID - ephID, start, end, err = ephemeral.GetId(rid, uint(addressSize), - timeNow.UnixNano()) + ephID, start, end, err = ephemeral.GetId( + rid, uint(addressSize), timeNow.UnixNano()) if err != nil { return message.RequestPayload{}, receptionID.EphemeralIdentity{}, - errors.Errorf("failed to generate "+ - "address ID from newly generated ID: %+v", err) + errors.Errorf("failed to generate address ID from newly "+ + "generated ID: %+v", err) } jww.DEBUG.Printf("address.GetId(%s, %d, %d) = %d", rid, addressSize, timeNow.UnixNano(), ephID.Int64()) } - jww.INFO.Printf("generated by singe use sender reception id for single use: %s, "+ - "ephId: %d, pubkey: %x, msg: %s", rid, ephID.Int64(), publicKey.Bytes(), msg) + jww.INFO.Printf("generated by singe use sender reception ID for single "+ + "use: %s, ephId: %d, pubkey: %x, msg: %s", + rid, ephID.Int64(), publicKey.Bytes(), msg) return msg, receptionID.EphemeralIdentity{ EphId: ephID, @@ -237,8 +239,8 @@ func makeIDs(msg message.RequestPayload, publicKey *cyclic.Int, }, nil } -// waitForTimeout is a long running thread which handles timing out a request. -// It can be canceled by channel +// waitForTimeout is a long-running thread which handles timing out a request. +// It can be canceled by channel. func waitForTimeout(kill chan bool, callback callbackWrapper, timeout time.Duration) { timer := time.NewTimer(timeout) select { diff --git a/single/responseProcessor.go b/single/responseProcessor.go index 7fca2e88bbcc979be0c8c9753f720cb5ad938ccd..33b02298df7a82c55a5446208db5b26c2b2460b4 100644 --- a/single/responseProcessor.go +++ b/single/responseProcessor.go @@ -12,9 +12,9 @@ import ( type callbackWrapper func(payload []byte, receptionID receptionID.EphemeralIdentity, round rounds.Round, err error) -// responceProcessor Message.Processor interface registered with cmix.Client. -// One is registered for each potential fingerprint. -type responceProcessor struct { +// responseProcessor is registered for each potential fingerprint. Adheres to +// the message.Processor interface registered with cmix.Client +type responseProcessor struct { sendingID receptionID.EphemeralIdentity c *message.Collator callback callbackWrapper @@ -25,7 +25,7 @@ type responceProcessor struct { // Process decrypts a response part and adds it to the collator - returning // a full response to the callback when all parts are received. -func (rsp *responceProcessor) Process(ecrMsg format.Message, +func (rsp *responseProcessor) Process(ecrMsg format.Message, receptionID receptionID.EphemeralIdentity, round rounds.Round) { diff --git a/ud/store/store.go b/ud/store/store.go index 64325e317bef67ef2d192ab64e70ba32da2d5365..45b7ffdc4e1e516445e0761f7bad08b9ca666e0c 100644 --- a/ud/store/store.go +++ b/ud/store/store.go @@ -8,6 +8,7 @@ import ( "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/primitives/fact" "gitlab.com/xx_network/primitives/netTime" + "io/fs" "strings" ) @@ -113,7 +114,7 @@ func NewOrLoadStore(kv *versioned.KV) (*Store, error) { if err := s.load(); err != nil { if strings.Contains(err.Error(), "object not found") || - strings.Contains(err.Error(), "no such file or directory") { + errors.Is(err, fs.ErrNotExist) { return s, s.save() } }