From f8a3912199841ce94c0fa30e6154148a6e228787 Mon Sep 17 00:00:00 2001 From: Benjamin Wenger <ben@elixxir.ioo> Date: Thu, 15 Oct 2020 13:43:12 -0700 Subject: [PATCH] finished fact stringification --- auth/baseFormat.go | 85 ++++++++++++++++++++++++++++++++++ auth/ecrformat.go | 73 +++++++++++++++++++++++++++++ auth/requestFormat.go | 8 ++++ interfaces/contact/contact.go | 41 ++++++++++++++++ interfaces/contact/fact.go | 36 ++++++-------- interfaces/contact/factList.go | 10 ++-- interfaces/contact/type.go | 31 ++++++++++++- 7 files changed, 258 insertions(+), 26 deletions(-) create mode 100644 auth/baseFormat.go create mode 100644 auth/ecrformat.go create mode 100644 auth/requestFormat.go diff --git a/auth/baseFormat.go b/auth/baseFormat.go new file mode 100644 index 000000000..1e39a57ef --- /dev/null +++ b/auth/baseFormat.go @@ -0,0 +1,85 @@ +package auth + +import ( + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/crypto/cyclic" +) + +const saltSize = 32 + +type format struct { + data []byte + pubkey []byte + salt []byte + ecrPayload []byte +} + +func newFormat(payloadSize, pubkeySize uint, pubkey *cyclic.Int, + salt []byte) format { + + if len(salt) != saltSize { + jww.FATAL.Panicf("Salt is wrong size, should be %v, is %v", + saltSize, len(salt)) + } + + if payloadSize < pubkeySize+saltSize { + jww.FATAL.Panicf("Size of format is too small, must be big " + + "enough to contain public key and salt") + } + + f := buildFormat(make([]byte, payloadSize), pubkeySize) + + copy(f.pubkey, pubkey.LeftpadBytes(uint64(pubkeySize))) + copy(f.salt, salt) + + return f +} + +func buildFormat(data []byte, pubkeySize uint) format { + f := format{ + data: data, + } + + f.pubkey = f.data[:pubkeySize] + f.salt = f.data[pubkeySize : pubkeySize+saltSize] + f.ecrPayload = f.data[pubkeySize+saltSize:] + return f +} + +func unmarshalFormat(b []byte, pubkeySize uint) (format, error) { + if uint(len(b)) < pubkeySize+saltSize { + return format{}, errors.New("Received format too small") + } + + return buildFormat(b, pubkeySize), nil +} + +func (f format) Marshal() []byte { + return f.data +} + +func (f format) GetPubKey(grp *cyclic.Group) *cyclic.Int { + return grp.NewIntFromBytes(f.pubkey) +} + +func (f format) GetSalt() []byte { + return f.salt +} + +func (f format) GetEcrPayload() []byte { + return f.ecrPayload +} + +func (f format) GetEcrPayloadLen() int { + return len(f.ecrPayload) +} + +func (f format) SetEcrPayload(ecr []byte) { + if len(ecr) != len(f.ecrPayload) { + jww.FATAL.Panicf("Passed ecr payload incorrect lengh. Expected:"+ + " %v, Recieved: %v", len(f.ecrPayload), len(ecr)) + } + + copy(f.ecrPayload, ecr) +} diff --git a/auth/ecrformat.go b/auth/ecrformat.go new file mode 100644 index 000000000..7943c501d --- /dev/null +++ b/auth/ecrformat.go @@ -0,0 +1,73 @@ +package auth + +import ( + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" +) + +const ownershipSize = 32 + +type ecrFormat struct { + data []byte + ownership []byte + payload []byte +} + +func newEcrFormat(size uint, ownership []byte) ecrFormat { + if size < ownershipSize { + jww.FATAL.Panicf("Size too small to hold") + } + + if len(ownership) != ownershipSize { + jww.FATAL.Panicf("ownership proof is the wrong size") + } + + f := buildEcrFormat(make([]byte, size)) + + copy(f.ownership, ownership) + + return f + +} + +func buildEcrFormat(data []byte) ecrFormat { + f := ecrFormat{ + data: data, + } + + f.ownership = f.data[:ownershipSize] + f.payload = f.data[ownershipSize:] + return f +} + +func unmarshalEcrFormat(b []byte) (ecrFormat, error) { + if len(b) < ownershipSize { + return ecrFormat{}, errors.New("Received ecr format too small") + } + + return buildEcrFormat(b), nil +} + +func (f ecrFormat) Marshal() []byte { + return f.data +} + +func (f ecrFormat) GetOwnership() []byte { + return f.ownership +} + +func (f ecrFormat) GetPayload() []byte { + return f.payload +} + +func (f ecrFormat) GetPayloadSize() int { + return len(f.payload) +} + +func (f ecrFormat) SetPayload(p []byte) { + if len(p) != len(f.payload) { + jww.FATAL.Panicf("Payload is the wrong length") + } + + copy(f.payload, p) +} diff --git a/auth/requestFormat.go b/auth/requestFormat.go new file mode 100644 index 000000000..de8e5031e --- /dev/null +++ b/auth/requestFormat.go @@ -0,0 +1,8 @@ +package auth + +type requestFormat struct { + ecrFormat + id []byte + facts []byte + message []byte +} diff --git a/interfaces/contact/contact.go b/interfaces/contact/contact.go index f67175fc8..769c7e826 100644 --- a/interfaces/contact/contact.go +++ b/interfaces/contact/contact.go @@ -6,8 +6,14 @@ import ( "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/xx_network/primitives/id" + "strings" + jww "github.com/spf13/jwalterweatherman" ) +const factDelimiter = "," +const factBreak = ";" + + // Contact implements the Contact interface defined in interface/contact.go, // in go, the structure is meant to be edited directly, the functions are for // bindings compatibility @@ -38,10 +44,22 @@ func (c Contact) GetFactList() interfaces.FactList { return FactList{source: &c} } +// json marshals the contact func (c Contact) Marshal() ([]byte, error) { return json.Marshal(&c) } +// converts facts to a delineated string with an ending character for transfer +// over the network +func (c Contact) StringifyFacts() string { + stringList := make([]string, len(c.Facts)) + for index, f := range c.Facts { + stringList[index] = f.Stringify() + } + + return strings.Join(stringList, factDelimiter) + factBreak +} + func Unmarshal(b []byte) (Contact, error) { c := Contact{} err := json.Unmarshal(b, &c) @@ -56,3 +74,26 @@ func Unmarshal(b []byte) (Contact, error) { } return c, nil } + +// splits the "facts" portion of the payload from the rest and returns them as +// facts +func UnstringifyFacts(s string) ([]Fact, string, error) { + parts := strings.SplitN(s, factBreak, 1) + if len(parts) != 2 { + return nil, "", errors.New("Invalid fact string passed") + } + factStrings := strings.Split(parts[0], factDelimiter) + + var factList []Fact + for _, fString := range factStrings { + fact, err := UnstringifyFact(fString) + if err != nil { + jww.WARN.Printf("Fact failed to unstringify, dropped: %s", + err) + } else { + factList = append(factList, fact) + } + + } + return factList, parts[1], nil +} diff --git a/interfaces/contact/fact.go b/interfaces/contact/fact.go index a5af2ab57..298b80b2a 100644 --- a/interfaces/contact/fact.go +++ b/interfaces/contact/fact.go @@ -1,14 +1,18 @@ package contact -import ( - "github.com/pkg/errors" -) - type Fact struct { Fact string T FactType } +func NewFact(ft FactType, fact string) (Fact, error) { + //todo: filter the fact string + return Fact{ + Fact: fact, + T: ft, + }, nil +} + func (f Fact) Get() string { return f.Fact } @@ -18,25 +22,15 @@ func (f Fact) Type() int { } // marshal is for transmission for UDB, not a part of the fact interface -func (f Fact) Marshal() []byte { - serial := []byte(f.Fact) - b := make([]byte, len(serial)+1) - b[0] = byte(f.T) - - copy(b[1:len(serial)-1], serial) - return b +func (f Fact) Stringify() string { + return f.T.Stringify() + f.Fact } -func UnmarshalFact(b []byte) (Fact, error) { - t := FactType(b[0]) - if !t.IsValid() { - return Fact{}, errors.Errorf("Fact is not a valid type: %s", t) +func UnstringifyFact(s string) (Fact, error) { + ft, err := UnstringifyFactType(s) + if err != nil { + return Fact{}, err } - f := string(b[1:]) - - return Fact{ - Fact: f, - T: t, - }, nil + return NewFact(ft, s) } diff --git a/interfaces/contact/factList.go b/interfaces/contact/factList.go index 5c39398fc..bf4cd5015 100644 --- a/interfaces/contact/factList.go +++ b/interfaces/contact/factList.go @@ -22,9 +22,11 @@ func (fl FactList) Add(fact string, factType int) error { if !ft.IsValid() { return errors.New("Invalid fact type") } - fl.source.Facts = append(fl.source.Facts, Fact{ - Fact: fact, - T: ft, - }) + f, err := NewFact(ft, fact) + if err != nil { + return err + } + + fl.source.Facts = append(fl.source.Facts, f) return nil } diff --git a/interfaces/contact/type.go b/interfaces/contact/type.go index 1b9bb8989..cc7263d5f 100644 --- a/interfaces/contact/type.go +++ b/interfaces/contact/type.go @@ -1,6 +1,10 @@ package contact -import "fmt" +import ( + "fmt" + "github.com/pkg/errors" + jww "github.com/spf13/jwalterweatherman" +) type FactType uint8 @@ -23,6 +27,31 @@ func (t FactType) String() string { } } +func (t FactType) Stringify() string { + switch t { + case Username: + return "U" + case Email: + return "E" + case Phone: + return "P" + } + jww.FATAL.Panicf("Unknown Fact FactType: %d", t) + return "error" +} + +func UnstringifyFactType(s string) (FactType, error) { + switch s { + case "U": + return Username, nil + case "E": + return Email, nil + case "P": + return Phone, nil + } + return 3, errors.Errorf("Unknown Fact FactType: %s", s) +} + func (t FactType) IsValid() bool { return t == Username || t == Email || t == Phone } -- GitLab