Skip to content
Snippets Groups Projects
Commit 57eb9893 authored by Benjamin Wenger's avatar Benjamin Wenger
Browse files

implemented first pass of sendCmix, further fleshed out the network.Manager object

parent a753a5b6
No related branches found
No related tags found
No related merge requests found
package params package params
import "time"
type CMIX struct { type CMIX struct {
Retries uint //maximum number of rounds to try and send on
RoundTries uint
Timeout time.Duration
} }
func GetDefaultCMIX() CMIX { func GetDefaultCMIX() CMIX {
return CMIX{Retries: 3} return CMIX{
RoundTries: 3,
Timeout: 10 * time.Second,
}
} }
...@@ -92,7 +92,7 @@ func negotiate(ctx *context.Context, session *e2e.Session) error { ...@@ -92,7 +92,7 @@ func negotiate(ctx *context.Context, session *e2e.Session) error {
e2eParams := params.GetDefaultE2E() e2eParams := params.GetDefaultE2E()
e2eParams.Type = params.KeyExchange e2eParams.Type = params.KeyExchange
cmixParams := params.GetDefaultCMIX() cmixParams := params.GetDefaultCMIX()
cmixParams.Retries = 20 cmixParams.RoundTries = 20
rounds, err := ctx.Manager.SendE2E(m, e2eParams, cmixParams) rounds, err := ctx.Manager.SendE2E(m, e2eParams, cmixParams)
// If the send fails, returns the error so it can be handled. The caller // If the send fails, returns the error so it can be handled. The caller
......
...@@ -39,14 +39,25 @@ type Manager struct { ...@@ -39,14 +39,25 @@ type Manager struct {
//contains the network instance //contains the network instance
instance *network.Instance instance *network.Instance
//channels
nodeRegistration chan *id.ID
//local pointer to user ID because it is used often
uid *id.ID
} }
// NewManager builds a new reception manager object using inputted key fields // NewManager builds a new reception manager object using inputted key fields
func NewManager(ctx *context.Context, uid *id.ID, privKey, pubKey, func NewManager(ctx *context.Context) (*Manager, error) {
salt []byte, partial *ndf.NetworkDefinition) (*Manager, error) {
//start comms //start comms
comms, err := client.NewClientComms(uid, pubKey, privKey, salt) //get the user from storage
user := ctx.Session.User()
cryptoUser := user.GetCryptographicIdentity()
comms, err := client.NewClientComms(cryptoUser.GetUserID(),
cryptoUser.GetRSA().GetPublic(), cryptoUser.GetRSA(),
cryptoUser.GetSalt())
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "failed to create"+ return nil, errors.WithMessage(err, "failed to create"+
" client network manager") " client network manager")
...@@ -65,6 +76,7 @@ func NewManager(ctx *context.Context, uid *id.ID, privKey, pubKey, ...@@ -65,6 +76,7 @@ func NewManager(ctx *context.Context, uid *id.ID, privKey, pubKey,
runners: stoppable.NewMulti("network.Manager"), runners: stoppable.NewMulti("network.Manager"),
health: health.Init(ctx, 5*time.Second), health: health.Init(ctx, 5*time.Second),
instance: instance, instance: instance,
uid: cryptoUser.GetUserID(),
} }
return cm, nil return cm, nil
......
...@@ -7,13 +7,19 @@ ...@@ -7,13 +7,19 @@
package network package network
import ( import (
"github.com/golang-collections/collections/set"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/elixxir/client/context/message" "gitlab.com/elixxir/client/context/message"
"gitlab.com/elixxir/client/context/params" "gitlab.com/elixxir/client/context/params"
"gitlab.com/elixxir/client/context/stoppable" "gitlab.com/elixxir/client/context/stoppable"
"gitlab.com/elixxir/comms/mixmessages"
"gitlab.com/elixxir/comms/network" "gitlab.com/elixxir/comms/network"
"gitlab.com/elixxir/crypto/csprng"
"gitlab.com/elixxir/primitives/format" "gitlab.com/elixxir/primitives/format"
"gitlab.com/xx_network/comms/connect"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"time"
jww "github.com/spf13/jwalterweatherman"
) )
// SendE2E sends an end-to-end payload to the provided recipient with // SendE2E sends an end-to-end payload to the provided recipient with
...@@ -36,7 +42,7 @@ func (m *Manager) SendE2E(msg message.Send, e2eP params.E2E, cmixP params.CMIX) ...@@ -36,7 +42,7 @@ func (m *Manager) SendE2E(msg message.Send, e2eP params.E2E, cmixP params.CMIX)
// of the message were sent or an error if it fails. // of the message were sent or an error if it fails.
// NOTE: Do not use this function unless you know what you are doing. // NOTE: Do not use this function unless you know what you are doing.
// This function always produces an error message in client logging. // This function always produces an error message in client logging.
func (m *Manager) SendUnsafe(m message.Send) ([]id.Round, error) { func (m *Manager) SendUnsafe(msg message.Send) ([]id.Round, error) {
return nil, nil return nil, nil
} }
...@@ -44,21 +50,105 @@ func (m *Manager) SendUnsafe(m message.Send) ([]id.Round, error) { ...@@ -44,21 +50,105 @@ func (m *Manager) SendUnsafe(m message.Send) ([]id.Round, error) {
// recipient. Note that both SendE2E and SendUnsafe call SendCMIX. // recipient. Note that both SendE2E and SendUnsafe call SendCMIX.
// Returns the round ID of the round the payload was sent or an error // Returns the round ID of the round the payload was sent or an error
// if it fails. // if it fails.
func (m *Manager) SendCMIX(msg format.Message) (id.Round, error) { func (m *Manager) SendCMIX(msg format.Message, param params.CMIX) (id.Round, error) {
if !m.health.IsRunning() { if !m.health.IsRunning() {
return 0, errors.New("Cannot send cmix message when the " + return 0, errors.New("Cannot send cmix message when the " +
"network is not healthy") "network is not healthy")
} }
return m.sendCMIX(msg) return m.sendCMIX(msg, param)
} }
// Internal send e2e which bypasses the network check, for use in SendE2E and // Internal send e2e which bypasses the network check, for use in SendE2E and
// SendUnsafe which do their own network checks // SendUnsafe which do their own network checks
func (m *Manager) sendCMIX(message format.Message) (id.Round, error) { func (m *Manager) sendCMIX(msg format.Message, param params.CMIX) (id.Round, error) {
//get the round to send on timeStart := time.Now()
m. attempted := set.New()
return 0, nil for numRoundTries := uint(0); numRoundTries < param.RoundTries; numRoundTries++ {
elapsed := time.Now().Sub(timeStart)
if elapsed < param.Timeout {
return 0, errors.New("Sending cmix message timed out")
} }
remainingTime := param.Timeout - elapsed
//find the best round to send to, excluding roudn which have been attempted
bestRound, _ := m.instance.GetWaitingRounds().GetUpcomingRealtime(remainingTime, attempted)
topology, firstNode := buildToplogy(bestRound.Topology)
//get they keys for the round, reject if any nodes do not have
//keying relationships
roundKeys, missingKeys := m.Context.Session.Cmix().GetRoundKeys(topology)
if len(missingKeys) > 0 {
go handleMissingNodeKeys(missingKeys)
continue
}
//get the gateway to transmit to
firstGateway := firstNode.DeepCopy()
firstGateway.SetType(id.Gateway)
transmitGateway, ok := m.Comms.GetHost(firstGateway)
if !ok {
jww.ERROR.Printf("Failed to get host for gateway %s", transmitGateway)
continue
}
//cutoff
//encrypt the message
salt := make([]byte, 32)
_, err := csprng.NewSystemRNG().Read(salt)
if err != nil {
return 0, errors.WithMessage(err, "Failed to generate "+
"salt, this should never happen")
}
encMsg, kmacs := roundKeys.Encrypt(msg, salt)
//build the message payload
msgPacket := &mixmessages.Slot{
SenderID: m.uid.Bytes(),
PayloadA: encMsg.GetPayloadA(),
PayloadB: encMsg.GetPayloadB(),
Salt: salt,
KMACs: kmacs,
}
//create the wrapper to the gateway
msg := &mixmessages.GatewaySlot{
Message: msgPacket,
RoundID: bestRound.ID,
}
//Add the mac proving ownership
msg.MAC = roundKeys.MakeClientGatewayKey(salt, network.GenerateSlotDigest(msg))
//Send the payload
gwSlotResp, err := m.Comms.SendPutMessage(transmitGateway, msg)
//if the comm errors or the message fails to send, continue retrying.
//return if it sends properly
if err != nil {
jww.ERROR.Printf("Failed to send message to %s: %s",
transmitGateway, err)
} else if gwSlotResp.Accepted {
return id.Round(bestRound.ID), nil
}
//add the round on to the list of attempted so it is not tried again
attempted.Insert(bestRound)
}
return 0, errors.New("failed to send the message")
}
func buildToplogy(nodes [][]byte) (*connect.Circuit, *id.ID) {
idList := make([]*id.ID, len(nodes))
for i, n := range nodes {
}
}
func handleMissingNodeKeys(nodes []*id.ID) {}
...@@ -40,3 +40,15 @@ func (rk *RoundKeys) Encrypt(msg format.Message, ...@@ -40,3 +40,15 @@ func (rk *RoundKeys) Encrypt(msg format.Message,
return ecrMsg, KMAC return ecrMsg, KMAC
} }
func (rk *RoundKeys) MakeClientGatewayKey(salt, digest []byte) []byte {
clientGatewayKey := cmix.GenerateClientGatewayKey(rk.keys[0].k)
h, _ := hash.NewCMixHash()
h.Write(clientGatewayKey)
h.Write(salt)
hashed := h.Sum(nil)
h.Reset()
h.Write(hashed)
h.Write(digest)
return h.Sum(nil)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment