diff --git a/auth/confirm.go b/auth/confirm.go index f13d3871d9669b52c66924cfb7e4f17bc89b080c..01dd82dbda9edaa62a368abfa67d3820f3f95176 100644 --- a/auth/confirm.go +++ b/auth/confirm.go @@ -36,7 +36,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, // check if the partner has an auth in progress // this takes the lock, from this point forward any errors need to release // the lock - storedContact, err := storage.Auth().GetReceivedRequest(partner.ID) + storedContact, theirSidHPubkeyA, err := storage.Auth().GetReceivedRequest(partner.ID) if err != nil { return 0, errors.Errorf("failed to find a pending Auth Request: %s", err) @@ -74,7 +74,7 @@ func ConfirmRequestAuth(partner contact.Contact, rng io.Reader, // we build the payload before we save because it is technically fallible // which can get into a bricked state if it fails cmixMsg := format.NewMessage(storage.Cmix().GetGroup().GetP().ByteLen()) - baseFmt := newBaseFormat(cmixMsg.ContentsSize(), grp.GetP().ByteLen()) + baseFmt := newBaseFormat(cmixMsg.ContentsSize(), grp.GetP().ByteLen(), interfaces.SidHPubKeyByteSize) ecrFmt := newEcrFormat(baseFmt.GetEcrPayloadLen()) // setup the encrypted payload diff --git a/auth/fmt.go b/auth/fmt.go index deb1dad1acf77f196fbda05c90153758cb3bc289..18f51d9390dc1d31a3cb382626f3e1af7d2b83a7 100644 --- a/auth/fmt.go +++ b/auth/fmt.go @@ -8,6 +8,7 @@ package auth import ( + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/crypto/cyclic" @@ -20,39 +21,43 @@ const saltSize = 32 type baseFormat struct { data []byte pubkey []byte + sidHpubkey []byte salt []byte ecrPayload []byte } -func newBaseFormat(payloadSize, pubkeySize int) baseFormat { - - if payloadSize < pubkeySize+saltSize { - jww.FATAL.Panicf("Size of baseFormat is too small, must be big " + - "enough to contain public key and salt") +func newBaseFormat(payloadSize, sidHPubkeySize, pubkeySize int ) baseFormat { + total := pubkeySize+sidHPubkeySize+saltSize + if payloadSize < total { + jww.FATAL.Panicf("Size of baseFormat is too small (%d), must be big " + + "enough to contain public key (%d) sidHPublicKey (%d) and salt (%d) " + + "which totals to %d", payloadSize, pubkeySize, sidHPubkeySize, saltSize, + total) } - f := buildBaseFormat(make([]byte, payloadSize), pubkeySize) + f := buildBaseFormat(make([]byte, payloadSize), pubkeySize, sidHPubkeySize) return f } -func buildBaseFormat(data []byte, pubkeySize int) baseFormat { +func buildBaseFormat(data []byte, pubkeySize, sidHPubkeySize int) baseFormat { f := baseFormat{ data: data, } f.pubkey = f.data[:pubkeySize] - f.salt = f.data[pubkeySize : pubkeySize+saltSize] - f.ecrPayload = f.data[pubkeySize+saltSize:] + f.sidHpubkey = f.data[pubkeySize: pubkeySize + sidHPubkeySize] + f.salt = f.data[pubkeySize + sidHPubkeySize: pubkeySize+sidHPubkeySize+saltSize] + f.ecrPayload = f.data[pubkeySize+sidHPubkeySize+saltSize:] return f } -func unmarshalBaseFormat(b []byte, pubkeySize int) (baseFormat, error) { +func unmarshalBaseFormat(b []byte, pubkeySize, sidHPubkeySize int) (baseFormat, error) { if len(b) < pubkeySize+saltSize { return baseFormat{}, errors.New("Received baseFormat too small") } - return buildBaseFormat(b, pubkeySize), nil + return buildBaseFormat(b, pubkeySize, sidHPubkeySize), nil } func (f baseFormat) Marshal() []byte { @@ -68,6 +73,10 @@ func (f baseFormat) SetPubKey(pubKey *cyclic.Int) { copy(f.pubkey, pubKeyBytes) } +func (f baseFormat) SetSidHPubKey(pubKey *sidh.PublicKey) { + pubKey.Export(f.sidHpubkey) +} + func (f baseFormat) GetSalt() []byte { return f.salt } @@ -171,7 +180,6 @@ func (f ecrFormat) SetPayload(p []byte) { type requestFormat struct { ecrFormat id []byte - msgPayload []byte } func newRequestFormat(ecrFmt ecrFormat) (requestFormat, error) { @@ -184,7 +192,6 @@ func newRequestFormat(ecrFmt ecrFormat) (requestFormat, error) { } rf.id = rf.payload[:id.ArrIDLen] - rf.msgPayload = rf.payload[id.ArrIDLen:] return rf, nil } @@ -195,20 +202,4 @@ func (rf requestFormat) GetID() (*id.ID, error) { func (rf requestFormat) SetID(myId *id.ID) { copy(rf.id, myId.Marshal()) -} - -func (rf requestFormat) SetMsgPayload(b []byte) { - if len(b) > len(rf.msgPayload) { - jww.FATAL.Panicf("Message Payload is too long") - } - - copy(rf.msgPayload, b) -} - -func (rf requestFormat) MsgPayloadLen() int { - return len(rf.msgPayload) -} - -func (rf requestFormat) GetMsgPayload() []byte { - return rf.msgPayload -} +} \ No newline at end of file diff --git a/auth/request.go b/auth/request.go index 1be24089150fd7ef7dcce0c6ffaaffb1324bab2e..0dd443e6442a0d55ee746b898215aa08e443f072 100644 --- a/auth/request.go +++ b/auth/request.go @@ -9,6 +9,7 @@ package auth import ( "fmt" + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces" @@ -28,7 +29,7 @@ import ( const terminator = ";" -func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, +func RequestAuth(partner, me contact.Contact, rng io.Reader, storage *storage.Session, net interfaces.NetworkManager) (id.Round, error) { /*edge checks generation*/ @@ -45,11 +46,6 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, "can only be sent from user's identity") } - // check that the message is properly formed - if strings.Contains(message, terminator) { - return 0, errors.Errorf("Message cannot contain '%s'", terminator) - } - //denote if this is a resend of an old request resend := false @@ -76,24 +72,13 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, /*generate embedded message structures and check payload*/ cmixMsg := format.NewMessage(storage.Cmix().GetGroup().GetP().ByteLen()) - baseFmt := newBaseFormat(cmixMsg.ContentsSize(), grp.GetP().ByteLen()) + baseFmt := newBaseFormat(cmixMsg.ContentsSize(), grp.GetP().ByteLen(), interfaces.SidHPubKeyByteSize) ecrFmt := newEcrFormat(baseFmt.GetEcrPayloadLen()) requestFmt, err := newRequestFormat(ecrFmt) if err != nil { return 0, errors.Errorf("failed to make request format: %+v", err) } - //check the payload fits - facts := me.Facts.Stringify() - msgPayload := facts + message + terminator - msgPayloadBytes := []byte(msgPayload) - - if len(msgPayloadBytes) > requestFmt.MsgPayloadLen() { - return 0, errors.Errorf("Combined message longer than space "+ - "available in payload; available: %v, length: %v", - requestFmt.MsgPayloadLen(), len(msgPayloadBytes)) - } - /*cryptographic generation*/ //generate salt salt := make([]byte, saltSize) @@ -103,17 +88,31 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, } var newPrivKey, newPubKey *cyclic.Int + var sidHPrivKeyA *sidh.PrivateKey + var sidHPubKeyA *sidh.PublicKey // in this case we have an ongoing request so we can resend the extant // request if resend { newPrivKey = sr.GetMyPrivKey() newPubKey = sr.GetMyPubKey() + sidHPrivKeyA = sr.GetMySidhPrivKeyA() + sidHPubKeyA = sr.GetMySidhPubKeyA() //in this case it is a new request and we must generate new keys } else { //generate new keypair newPrivKey = diffieHellman.GeneratePrivateKey(256, grp, rng) newPubKey = diffieHellman.GeneratePublicKey(newPrivKey, grp) + + sidHPrivKeyA = sidh.NewPrivateKey(interfaces.SidHKeyId, sidh.KeyVariantSidhA) + sidHPubKeyA = sidh.NewPublicKey(interfaces.SidHKeyId, sidh.KeyVariantSidhA) + + if err = sidHPrivKeyA.Generate(rng); err!=nil{ + return 0, errors.WithMessagef(err, "Failed to send requrest due to " + + "failure to generate SidH A private key") + } + sidHPrivKeyA.GeneratePublicKey(sidHPubKeyA) + } //generate ownership proof @@ -125,7 +124,6 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, /*encrypt payload*/ requestFmt.SetID(storage.GetUser().ReceptionID) - requestFmt.SetMsgPayload(msgPayloadBytes) ecrFmt.SetOwnership(ownership) ecrPayload, mac := cAuth.Encrypt(newPrivKey, partner.DhPubKey, salt, ecrFmt.data, grp) @@ -135,6 +133,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, /*construct message*/ baseFmt.SetEcrPayload(ecrPayload) baseFmt.SetSalt(salt) + baseFmt.SetSidHPubKey(sidHPubKeyA) baseFmt.SetPubKey(newPubKey) cmixMsg.SetKeyFP(requestfp) @@ -150,7 +149,7 @@ func RequestAuth(partner, me contact.Contact, message string, rng io.Reader, //store the in progress auth if !resend { err = storage.Auth().AddSent(partner.ID, partner.DhPubKey, newPrivKey, - newPubKey, confirmFp) + newPubKey, sidHPrivKeyA, sidHPubKeyA, confirmFp) if err != nil { return 0, errors.Errorf("Failed to store auth request: %s", err) } diff --git a/cmd/root.go b/cmd/root.go index 0b1028f1a9ecf0f7a49b635f0f6287039549564d..16bd9bb3704780db51b9fcc39261bce8870d28be 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -28,6 +28,7 @@ import ( "runtime/pprof" "strconv" "strings" + "sync" "time" ) @@ -188,38 +189,51 @@ var rootCmd = &cobra.Command{ paramsUnsafe := params.GetDefaultUnsafe() sendCnt := int(viper.GetUint("sendCount")) - sendDelay := time.Duration(viper.GetUint("sendDelay")) - for i := 0; i < sendCnt; i++ { - fmt.Printf("Sending to %s: %s\n", recipientID, msgBody) - var roundIDs []id.Round - var roundTimeout time.Duration - if unsafe { - roundIDs, err = client.SendUnsafe(msg, - paramsUnsafe) - roundTimeout = paramsUnsafe.Timeout - } else { - roundIDs, _, _, err = client.SendE2E(msg, - paramsE2E) - roundTimeout = paramsE2E.Timeout - } - if err != nil { - jww.FATAL.Panicf("%+v", err) - } - - // Construct the callback function which prints out the rounds' results - f := func(allRoundsSucceeded, timedOut bool, - rounds map[id.Round]api.RoundResult) { - printRoundResults(allRoundsSucceeded, timedOut, rounds, roundIDs, msg) - } - - // Have the client report back the round results - err = client.GetRoundResults(roundIDs, roundTimeout, f) - if err != nil { - jww.FATAL.Panicf("%+v", err) + //sendDelay := time.Duration(viper.GetUint("sendDelay")) + wg := sync.WaitGroup{} + go func(){ + for i := 0; i < sendCnt; i++ { + wg.Add(1) + go func(locali int) { + fmt.Printf("Sending to %s: %s\n", recipientID, msgBody) + var roundIDs []id.Round + var roundTimeout time.Duration + if unsafe { + roundIDs, err = client.SendUnsafe(msg, + paramsUnsafe) + roundTimeout = paramsUnsafe.Timeout + } else { + roundIDs, _, _, err = client.SendE2E(msg, + paramsE2E) + roundTimeout = paramsE2E.Timeout + } + if err != nil { + jww.FATAL.Panicf("%+v", err) + } + + // Construct the callback function which prints out the rounds' results + f := func(allRoundsSucceeded, timedOut bool, + rounds map[id.Round]api.RoundResult) { + printRoundResults(allRoundsSucceeded, timedOut, rounds, roundIDs, msg) + } + + // Have the client report back the round results + for j:=0;j<5&&(err==nil || i==0);j++{ + err = client.GetRoundResults(roundIDs, roundTimeout, f) + if err != nil { + jww.WARN.Printf("Received error on send %d attempt %d: %+v", locali, j, err) + } + } + + if err!=nil{ + jww.FATAL.Panicf("%v",err) + } + + }(i) + + //time.Sleep(sendDelay * time.Millisecond) } - - time.Sleep(sendDelay * time.Millisecond) - } + }() // Wait until message timeout or we receive enough then exit // TODO: Actually check for how many messages we've received @@ -250,7 +264,9 @@ var rootCmd = &cobra.Command{ if roundsNotepad != nil { roundsNotepad.INFO.Printf("\n%s", client.GetNetworkInterface().GetVerboseRounds()) } - + jww.INFO.Printf("Waiting on all sending to finish to exit") + wg.Done() + jww.INFO.Printf("All sending to finished, exiting") err = client.StopNetworkFollower() if err != nil { jww.WARN.Printf( diff --git a/go.mod b/go.mod index ff44d825c890961a44dfe12a7694b2e994c1d7b4..ce709d8f2bbc21999b8a9dd5ea57f4ab756048eb 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,8 @@ module gitlab.com/elixxir/client go 1.13 require ( + github.com/cloudflare/circl v1.0.1-0.20211008185751-59b49bc148ce + github.com/cloudflare/sidh v0.0.0-20190228162259-d2f0f90e08aa // indirect github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 github.com/golang/protobuf v1.5.2 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect @@ -24,7 +26,7 @@ require ( gitlab.com/xx_network/comms v0.0.4-0.20211008201730-adc33de72c11 gitlab.com/xx_network/crypto v0.0.5-0.20211006222352-8e0ac37b86b0 gitlab.com/xx_network/primitives v0.0.4-0.20210915220237-70cb4551d6f3 - golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 golang.org/x/net v0.0.0-20210525063256-abc453219eb5 google.golang.org/genproto v0.0.0-20210105202744-fe13368bc0e1 // indirect google.golang.org/grpc v1.38.0 diff --git a/go.sum b/go.sum index 1a84bc874207b011f11f7bd879fef1926bd73906..4088ee88e2e2406482fafbeae05185282c7a7893 100644 --- a/go.sum +++ b/go.sum @@ -25,9 +25,16 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.0.0 h1:64b6pyfCFbYm623ncIkYGNZaOcmIbyd+CjyMi2L9vdI= +github.com/cloudflare/circl v1.0.0/go.mod h1:MhjB3NEEhJbTOdLLq964NIUisXDxaE1WkQPUxtgZXiY= +github.com/cloudflare/circl v1.0.1-0.20211008185751-59b49bc148ce h1:2s+cfEmFVdtV8Z85o6U0QxtNhCXDCMR2OLZKgL39ApI= +github.com/cloudflare/circl v1.0.1-0.20211008185751-59b49bc148ce/go.mod h1:tnEeRn/onb0b4Ew40H00boTlcVMHveaTzi6m+/iMruw= +github.com/cloudflare/sidh v0.0.0-20190228162259-d2f0f90e08aa h1:2pQJShMsIfrl5+NnJRzWSmp6FDUZY3LcnviKOYn9qWM= +github.com/cloudflare/sidh v0.0.0-20190228162259-d2f0f90e08aa/go.mod h1:o/DcCuWFr9jFzwO+c3y1hhwqKHHKfJ7HvLhWUwRnqfo= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -301,6 +308,8 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -356,6 +365,7 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -369,6 +379,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210319071255-635bc2c9138d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210902050250-f475640dd07b h1:S7hKs0Flbq0bbc9xgYt4stIEG1zNDFqyrPwAX2Wj/sE= +golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/interfaces/sidh.go b/interfaces/sidh.go new file mode 100644 index 0000000000000000000000000000000000000000..59cc9affe603d26336c4ee58200674e602e012e2 --- /dev/null +++ b/interfaces/sidh.go @@ -0,0 +1,9 @@ +package interfaces + +import "github.com/cloudflare/circl/dh/sidh" + +const SidHKeyId = sidh.Fp503 +var SidHPubKeyBitSize = sidh.NewPublicKey(sidh.Fp503, sidh.KeyVariantSidhA).Size() +var SidHPubKeyByteSize = SidHPubKeyBitSize /8 +var SidHPrivKeyBitSize = sidh.NewPrivateKey(sidh.Fp503, sidh.KeyVariantSidhA).Size() +var SidHPrivKeyByteSize = SidHPrivKeyBitSize /8 diff --git a/storage/auth/request.go b/storage/auth/request.go index b6088352d29a3d0dc584f635ac7d0d26db021bad..0520da29ffe627c93f6eafd10b446286c2511aab 100644 --- a/storage/auth/request.go +++ b/storage/auth/request.go @@ -8,6 +8,7 @@ package auth import ( + "github.com/cloudflare/circl/dh/sidh" "gitlab.com/elixxir/crypto/contact" "sync" ) @@ -28,6 +29,9 @@ type request struct { // Data if receive receive *contact.Contact + //sidHPublic key of partner + theirSidHPubKeyA *sidh.PublicKey + // mux to ensure there is not concurrent access mux sync.Mutex } diff --git a/storage/auth/sentRequest.go b/storage/auth/sentRequest.go index af09eb475484cd1fc25f9fd18df197c5a2ff07e0..e384eae9ed7a79d961afeddc4f5b7da9e376c525 100644 --- a/storage/auth/sentRequest.go +++ b/storage/auth/sentRequest.go @@ -10,8 +10,10 @@ package auth import ( "encoding/hex" "encoding/json" + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/primitives/format" @@ -28,6 +30,8 @@ type SentRequest struct { partnerHistoricalPubKey *cyclic.Int myPrivKey *cyclic.Int myPubKey *cyclic.Int + mySidHPrivKeyA *sidh.PrivateKey + mySidHPubKeyA *sidh.PublicKey fingerprint format.Fingerprint } @@ -35,6 +39,8 @@ type sentRequestDisk struct { PartnerHistoricalPubKey []byte MyPrivKey []byte MyPubKey []byte + MySidHPrivKey []byte + mySidHPubKey []byte Fingerprint []byte } @@ -71,6 +77,19 @@ func loadSentRequest(kv *versioned.KV, partner *id.ID, grp *cyclic.Group) (*Sent "key with %s for SentRequest Auth", partner) } + mySidHPrivKeyA := sidh.NewPrivateKey(interfaces.SidHKeyId, sidh.KeyVariantSidhA) + if err = mySidHPrivKeyA.Import(srd.MySidHPrivKey); err != nil { + return nil, errors.WithMessagef(err, "Failed to decode sidh private key "+ + "with %s for SentRequest Auth", partner) + } + + mySidHPubKeyA := sidh.NewPublicKey(interfaces.SidHKeyId, sidh.KeyVariantSidhA) + if err = mySidHPubKeyA.Import(srd.mySidHPubKey); err != nil { + return nil, errors.WithMessagef(err, "Failed to decode sidh public "+ + "key with %s for SentRequest Auth", partner) + } + + fp := format.Fingerprint{} copy(fp[:], srd.Fingerprint) @@ -122,10 +141,17 @@ func (sr *SentRequest) save() error { jww.INFO.Printf("saveSentRequest fingerprint: %s", hex.EncodeToString(sr.fingerprint[:])) + sidHPriv := make([]byte, interfaces.SidHPrivKeyByteSize) + sidHPub := make([]byte, interfaces.SidHPubKeyByteSize) + sr.mySidHPrivKeyA.Export(sidHPriv) + sr.mySidHPubKeyA.Export(sidHPub) + ipd := sentRequestDisk{ PartnerHistoricalPubKey: historicalPubKey, MyPrivKey: privKey, MyPubKey: pubKey, + MySidHPrivKey: sidHPriv, + mySidHPubKey: sidHPub, Fingerprint: sr.fingerprint[:], } @@ -165,6 +191,14 @@ func (sr *SentRequest) GetMyPubKey() *cyclic.Int { return sr.myPubKey } +func (sr *SentRequest) GetMySidhPrivKeyA() *sidh.PrivateKey { + return sr.mySidHPrivKeyA +} + +func (sr *SentRequest) GetMySidhPubKeyA() *sidh.PublicKey { + return sr.mySidHPubKeyA +} + func (sr *SentRequest) GetFingerprint() format.Fingerprint { return sr.fingerprint } diff --git a/storage/auth/store.go b/storage/auth/store.go index 341bc74c01639163b9c22666263ab23b7812b1a8..3ee5e5b41bb3922a70e6456bdecc877fd52de62f 100644 --- a/storage/auth/store.go +++ b/storage/auth/store.go @@ -9,8 +9,10 @@ package auth import ( "encoding/json" + "github.com/cloudflare/circl/dh/sidh" "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/storage/utility" "gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/crypto/contact" @@ -20,6 +22,7 @@ import ( "gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/netTime" "sync" + "time" ) const NoRequest = "Request Not Found" @@ -126,8 +129,14 @@ func LoadStore(kv *versioned.KV, grp *cyclic.Group, privKeys []*cyclic.Int) (*St jww.FATAL.Panicf("Failed to load stored contact for: %+v", err) } + key, err := utility.LoadSidHPubKeyA(kv, c.ID) + if err != nil { + jww.FATAL.Panicf("Failed to load stored contact for: %+v", err) + } + rid = c.ID r.receive = &c + r.theirSidHPubKeyA = key default: jww.FATAL.Panicf("Unknown request type: %d", r.rt) @@ -166,7 +175,8 @@ func (s *Store) save() error { } func (s *Store) AddSent(partner *id.ID, partnerHistoricalPubKey, myPrivKey, - myPubKey *cyclic.Int, fp format.Fingerprint) error { + myPubKey *cyclic.Int, sidHPrivA *sidh.PrivateKey, sidHPubA *sidh.PublicKey, + fp format.Fingerprint) error { s.mux.Lock() defer s.mux.Unlock() @@ -181,6 +191,8 @@ func (s *Store) AddSent(partner *id.ID, partnerHistoricalPubKey, myPrivKey, partnerHistoricalPubKey: partnerHistoricalPubKey, myPrivKey: myPrivKey, myPubKey: myPubKey, + mySidHPubKeyA: sidHPubA, + mySidHPrivKeyA: sidHPrivA, fingerprint: fp, } @@ -214,7 +226,7 @@ func (s *Store) AddSent(partner *id.ID, partnerHistoricalPubKey, myPrivKey, return nil } -func (s *Store) AddReceived(c contact.Contact) error { +func (s *Store) AddReceived(c contact.Contact, key *sidh.PublicKey) error { s.mux.Lock() defer s.mux.Unlock() jww.DEBUG.Printf("AddReceived new contact: %s", c.ID) @@ -227,6 +239,23 @@ func (s *Store) AddReceived(c contact.Contact) error { jww.FATAL.Panicf("Failed to save contact for partner %s", c.ID.String()) } + if err := utility.StoreSidHPubKeyA(s.kv, c.ID, key); err != nil { + jww.FATAL.Panicf("Failed to save contact for partner %s", c.ID.String()) + } + + keyBytes :=make([]byte, interfaces.SidHPubKeyByteSize) + key.Export(keyBytes) + type Object struct { + // Used to determine version Upgrade, if any + Version uint64 + + // Set when this object is written + Timestamp time.Time + + // Serialized version of original object + Data []byte + } + r := &request{ rt: Receive, sent: nil, @@ -288,13 +317,13 @@ func (s *Store) GetFingerprint(fp format.Fingerprint) (FingerprintType, // it exists. If it returns, then it takes the lock to ensure that there is only // one operator at a time. The user of the API must release the lock by calling // store.delete() or store.Failed() with the partner ID. -func (s *Store) GetReceivedRequest(partner *id.ID) (contact.Contact, error) { +func (s *Store) GetReceivedRequest(partner *id.ID) (contact.Contact, *sidh.PublicKey, error) { s.mux.RLock() r, ok := s.requests[*partner] s.mux.RUnlock() if !ok { - return contact.Contact{}, errors.Errorf("Received request not "+ + return contact.Contact{}, nil, errors.Errorf("Received request not "+ "found: %s", partner) } @@ -309,11 +338,11 @@ func (s *Store) GetReceivedRequest(partner *id.ID) (contact.Contact, error) { if !ok { r.mux.Unlock() - return contact.Contact{}, errors.Errorf("Received request not "+ + return contact.Contact{}, nil, errors.Errorf("Received request not "+ "found: %s", partner) } - return *r.receive, nil + return *r.receive,r.theirSidHPubKeyA, nil } // GetReceivedRequestData returns the contact representing the receive request diff --git a/storage/utility/sidH.go b/storage/utility/sidH.go new file mode 100644 index 0000000000000000000000000000000000000000..d744a04121d697471a0e3dff44bdf20d13934b86 --- /dev/null +++ b/storage/utility/sidH.go @@ -0,0 +1,45 @@ +package utility + +import ( + "fmt" + "github.com/cloudflare/circl/dh/sidh" + "gitlab.com/elixxir/client/interfaces" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/xx_network/primitives/id" + "gitlab.com/xx_network/primitives/netTime" +) + +const currentSidHPubKeyAVersion = 0 + +func StoreSidHPubKeyA(kv *versioned.KV, id *id.ID, sidH *sidh.PublicKey) error { + now := netTime.Now() + + sidHBytes := make([]byte, sidH.Size()) + sidH.Export(sidHBytes) + + obj := versioned.Object{ + Version: currentSidHPubKeyAVersion, + Timestamp: now, + Data: sidHBytes, + } + + return kv.Set(makeSidHtKeyA(id), currentSidHPubKeyAVersion, &obj) +} + +func LoadSidHPubKeyA(kv *versioned.KV, cid *id.ID) (*sidh.PublicKey, error) { + vo, err := kv.Get(makeSidHtKeyA(cid), currentSidHPubKeyAVersion) + if err != nil { + return nil, err + } + + sidHPubkey := sidh.NewPublicKey(interfaces.SidHKeyId, sidh.KeyVariantSidhA) + return sidHPubkey, sidHPubkey.Import(vo.Data) +} + +func DeleteSidHPubKeyA(kv *versioned.KV, cid *id.ID) error { + return kv.Delete(makeSidHtKeyA(cid), currentSidHPubKeyAVersion) +} + +func makeSidHtKeyA(cid *id.ID) string { + return fmt.Sprintf("SidKPubKeyA:%s", cid) +}