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

made e2e encryption able to support alternate users and temporary...

made e2e encryption able to support alternate users and temporary relationships that dont store to disk
parent 7117e876
No related branches found
No related tags found
3 merge requests!510Release,!207WIP: Client Restructure,!203Symmetric broadcast
......@@ -13,7 +13,7 @@ type fpGenerator struct {
}
func (fp *fpGenerator) AddKey(k *session.Cypher) {
err := fp.net.AddFingerprint(fp.myID, k.Fingerprint(), &processor{
err := fp.net.AddFingerprint(fp.myDefaultID, k.Fingerprint(), &processor{
cy: k,
m: fp.manager,
})
......@@ -24,5 +24,5 @@ func (fp *fpGenerator) AddKey(k *session.Cypher) {
}
func (fp *fpGenerator) DeleteKey(k *session.Cypher) {
fp.net.DeleteFingerprint(fp.myID, k.Fingerprint())
fp.net.DeleteFingerprint(fp.myDefaultID, k.Fingerprint())
}
......@@ -94,19 +94,28 @@ type Handler interface {
// AddPartner adds a partner. Automatically creates both send and receive
// sessions using the passed cryptographic data and per the parameters sent
AddPartner(partnerID *id.ID, partnerPubKey, myPrivKey *cyclic.Int,
partnerSIDHPubKey *sidh.PublicKey, mySIDHPrivKey *sidh.PrivateKey,
sendParams, receiveParams session.Params, myID *id.ID, myPrivateKey *cyclic.Int, temporary bool) (*partner.Manager, error)
// 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
AddPartner(myID *id.ID, myPrivateKey *cyclic.Int, partnerID *id.ID,
partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey,
mySIDHPrivKey *sidh.PrivateKey, sendParams,
receiveParams session.Params, temporary bool) (*partner.Manager, error)
// GetPartner returns the partner per its ID, if it exists
GetPartner(partnerID *id.ID) (*partner.Manager, error)
// myID is your ID in the relationship, if left blank, it will
// assume to be your defaultID
GetPartner(partnerID *id.ID, myID *id.ID) (*partner.Manager, error)
// DeletePartner removes the associated contact from the E2E store
DeletePartner(partnerId *id.ID) error
// myID is your ID in the relationship, if left blank, it will
// assume to be your defaultID
DeletePartner(partnerId *id.ID, myID *id.ID) error
// GetAllPartnerIDs returns a list of all partner IDs that the user has
// an E2E relationship with.
GetAllPartnerIDs() []*id.ID
GetAllPartnerIDs(myID *id.ID) []*id.ID
/* === Services ========================================================= */
......
......@@ -23,7 +23,7 @@ type manager struct {
*receive.Switchboard
partitioner parse.Partitioner
net network.Manager
myID *id.ID
myDefaultID *id.ID
rng *fastRNG.StreamGenerator
events event.Manager
grp *cyclic.Group
......@@ -31,12 +31,16 @@ type manager struct {
}
// Init Creates stores. After calling, use load
func Init(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int, grp *cyclic.Group) error {
return ratchet.New(kv, myID, privKey, grp)
// Passes a default ID and public key which is used for relationship with
// partners when no default ID is selected
func Init(kv *versioned.KV, myDefaultID *id.ID, privKey *cyclic.Int, grp *cyclic.Group) error {
return ratchet.New(kv, myDefaultID, privKey, grp)
}
// Load returns an e2e manager from storage
func Load(kv *versioned.KV, net network.Manager, myID *id.ID,
// Passes a default ID which is used for relationship with
// partners when no default ID is selected
func Load(kv *versioned.KV, net network.Manager, myDefaultID *id.ID,
grp *cyclic.Group, rng *fastRNG.StreamGenerator, events event.Manager) (Handler, error) {
//build the manager
......@@ -44,14 +48,14 @@ func Load(kv *versioned.KV, net network.Manager, myID *id.ID,
Switchboard: receive.New(),
partitioner: parse.NewPartitioner(kv, net.GetMaxMessageLength()),
net: net,
myID: myID,
myDefaultID: myDefaultID,
events: events,
grp: grp,
}
var err error
//load the ratchets
m.Ratchet, err = ratchet.Load(kv, myID, grp,
m.Ratchet, err = ratchet.Load(kv, myDefaultID, grp,
&fpGenerator{m}, net, rng)
if err != nil {
return nil, err
......@@ -92,15 +96,15 @@ func (m *manager) StartProcesses() (stoppable.Stoppable, error) {
// EnableUnsafeReception enables the reception of unsafe message by registering
// bespoke services for reception. For debugging only!
func (m *manager) EnableUnsafeReception() {
m.net.AddService(m.myID, message.Service{
Identifier: m.myID[:],
m.net.AddService(m.myDefaultID, message.Service{
Identifier: m.myDefaultID[:],
Tag: ratchet.Silent,
}, &UnsafeProcessor{
m: m,
tag: ratchet.Silent,
})
m.net.AddService(m.myID, message.Service{
Identifier: m.myID[:],
m.net.AddService(m.myDefaultID, message.Service{
Identifier: m.myDefaultID[:],
Tag: ratchet.E2e,
}, &UnsafeProcessor{
m: m,
......
......@@ -216,6 +216,11 @@ func (m *Manager) GetPartnerID() *id.ID {
return m.partner.DeepCopy()
}
// GetMyID returns a copy of the ID used as self.
func (m *Manager) GetMyID() *id.ID {
return m.myID.DeepCopy()
}
// GetSendSession gets the Send session of the passed ID. Returns nil if no
// session is found.
func (m *Manager) GetSendSession(sid session.SessionID) *session.Session {
......@@ -245,6 +250,11 @@ func (m *Manager) TriggerNegotiations() []*session.Session {
return m.send.TriggerNegotiation()
}
// IsTemporary returns if this manager stores to disk or only in ram
func (m *Manager) IsTemporary() bool {
return m.kv.IsMemStore()
}
func (m *Manager) GetMyOriginPrivateKey() *cyclic.Int {
return m.originMyPrivKey.DeepCopy()
}
......
......@@ -8,7 +8,6 @@
package ratchet
import (
"encoding/json"
"github.com/cloudflare/circl/dh/sidh"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
......@@ -21,14 +20,11 @@ import (
"gitlab.com/elixxir/crypto/diffieHellman"
"gitlab.com/elixxir/crypto/fastRNG"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/netTime"
"sync"
)
const (
currentStoreVersion = 0
packagePrefix = "e2eSession"
storeKey = "Ratchet"
pubKeyKey = "DhPubKey"
privKeyKey = "DhPrivKey"
)
......@@ -36,12 +32,12 @@ const (
var NoPartnerErrorStr = "No relationship with partner found"
type Ratchet struct {
managers map[id.ID]*partner.Manager
managers map[relationshipIdentity]*partner.Manager
mux sync.RWMutex
myID *id.ID
dhPrivateKey *cyclic.Int
dhPublicKey *cyclic.Int
defaultID *id.ID
defaultDHPrivateKey *cyclic.Int
defaultDHPublicKey *cyclic.Int
grp *cyclic.Group
cyHandler session.CypherHandler
......@@ -53,6 +49,7 @@ type Ratchet struct {
servicesmux sync.RWMutex
kv *versioned.KV
memKv *versioned.KV
}
// New creates a new store for the passed user id and private key.
......@@ -69,12 +66,12 @@ func New(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int,
kv = kv.Prefix(packagePrefix)
r := &Ratchet{
managers: make(map[id.ID]*partner.Manager),
managers: make(map[relationshipIdentity]*partner.Manager),
services: make(map[string]message.Processor),
myID: myID,
dhPrivateKey: privKey,
dhPublicKey: pubKey,
defaultID: myID,
defaultDHPrivateKey: privKey,
defaultDHPublicKey: pubKey,
kv: kv,
......@@ -96,90 +93,46 @@ func New(kv *versioned.KV, myID *id.ID, privKey *cyclic.Int,
return r.save()
}
// Load loads an extant ratchet from disk
func Load(kv *versioned.KV, myID *id.ID, grp *cyclic.Group,
cyHandler session.CypherHandler, services Services, rng *fastRNG.StreamGenerator) (
*Ratchet, error) {
kv = kv.Prefix(packagePrefix)
r := &Ratchet{
managers: make(map[id.ID]*partner.Manager),
services: make(map[string]message.Processor),
myID: myID,
kv: kv,
cyHandler: cyHandler,
grp: grp,
rng: rng,
sInteface: services,
}
obj, err := kv.Get(storeKey, currentStoreVersion)
if err != nil {
return nil, err
}
err = r.unmarshal(obj.Data)
if err != nil {
return nil, err
}
// add standard services
if err = r.AddService(Silent, nil); err != nil {
jww.FATAL.Panicf("Could not add standard %r "+
"service: %+v", Silent, err)
}
if err = r.AddService(E2e, nil); err != nil {
jww.FATAL.Panicf("Could not add standard %r "+
"service: %+v", E2e, err)
}
return r, nil
}
func (r *Ratchet) save() error {
now := netTime.Now()
data, err := r.marshal()
if err != nil {
return err
}
obj := versioned.Object{
Version: currentStoreVersion,
Timestamp: now,
Data: data,
}
return r.kv.Set(storeKey, currentStoreVersion, &obj)
}
// AddPartner adds a partner. Automatically creates both send and receive
// sessions using the passed cryptographic data and per the parameters sent
func (r *Ratchet) AddPartner(partnerID *id.ID, partnerPubKey,
myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey,
func (r *Ratchet) AddPartner(myID *id.ID, myPrivateKey *cyclic.Int, partnerID *id.ID,
partnerPubKey, myPrivKey *cyclic.Int, partnerSIDHPubKey *sidh.PublicKey,
mySIDHPrivKey *sidh.PrivateKey, sendParams,
receiveParams session.Params) (*partner.Manager, error) {
receiveParams session.Params, temporary bool) (*partner.Manager, error) {
r.mux.Lock()
defer r.mux.Unlock()
if myID == nil {
myID = r.defaultID
}
if myPrivateKey == nil {
myPrivateKey = r.defaultDHPrivateKey
}
jww.INFO.Printf("Adding Partner %r:\n\tMy Private Key: %r"+
"\n\tPartner Public Key: %r",
"\n\tPartner Public Key: %r to %s",
partnerID,
myPrivKey.TextVerbose(16, 0),
partnerPubKey.TextVerbose(16, 0))
partnerPubKey.TextVerbose(16, 0), myID)
rship := makeRelationshipIdentity(partnerID, myID)
if _, ok := r.managers[*partnerID]; ok {
if _, ok := r.managers[rship]; ok {
return nil, errors.New("Cannot overwrite existing partner")
}
m := partner.NewManager(r.kv, r.myID, partnerID, myPrivKey, partnerPubKey,
//pass a memory kv if it is supposed to be temporary
kv := r.kv
if temporary {
kv = r.memKv
}
m := partner.NewManager(kv, r.defaultID, partnerID, myPrivKey, partnerPubKey,
mySIDHPrivKey, partnerSIDHPubKey,
sendParams, receiveParams, r.cyHandler, r.grp, r.rng)
r.managers[*partnerID] = m
r.managers[rship] = m
if err := r.save(); err != nil {
jww.FATAL.Printf("Failed to add Partner %r: Save of store failed: %r",
partnerID, err)
......@@ -192,11 +145,15 @@ func (r *Ratchet) AddPartner(partnerID *id.ID, partnerPubKey,
}
// GetPartner returns the partner per its ID, if it exists
func (r *Ratchet) GetPartner(partnerID *id.ID) (*partner.Manager, error) {
func (r *Ratchet) GetPartner(partnerID *id.ID, myID *id.ID) (*partner.Manager, error) {
r.mux.RLock()
defer r.mux.RUnlock()
m, ok := r.managers[*partnerID]
if myID == nil {
myID = r.defaultID
}
m, ok := r.managers[makeRelationshipIdentity(partnerID, myID)]
if !ok {
return nil, errors.New(NoPartnerErrorStr)
......@@ -206,8 +163,13 @@ func (r *Ratchet) GetPartner(partnerID *id.ID) (*partner.Manager, error) {
}
// DeletePartner removes the associated contact from the E2E store
func (r *Ratchet) DeletePartner(partnerId *id.ID) error {
m, ok := r.managers[*partnerId]
func (r *Ratchet) DeletePartner(partnerId *id.ID, myID *id.ID) error {
if myID == nil {
myID = r.defaultID
}
rShip := makeRelationshipIdentity(partnerId, myID)
m, ok := r.managers[rShip]
if !ok {
return errors.New(NoPartnerErrorStr)
}
......@@ -219,21 +181,24 @@ func (r *Ratchet) DeletePartner(partnerId *id.ID) error {
//delete services
r.delete(m)
delete(r.managers, *partnerId)
delete(r.managers, rShip)
return r.save()
}
// GetAllPartnerIDs returns a list of all partner IDs that the user has
// an E2E relationship with.
func (r *Ratchet) GetAllPartnerIDs() []*id.ID {
func (r *Ratchet) GetAllPartnerIDs(myID *id.ID) []*id.ID {
r.mux.RLock()
defer r.mux.RUnlock()
partnerIds := make([]*id.ID, 0, len(r.managers))
for partnerId := range r.managers {
partnerIds = append(partnerIds, &partnerId)
for _, m := range r.managers {
if m.GetMyID().Cmp(myID) {
partnerIds = append(partnerIds, m.GetPartnerID())
}
}
return partnerIds
......@@ -241,72 +206,10 @@ func (r *Ratchet) GetAllPartnerIDs() []*id.ID {
// GetDHPrivateKey returns the diffie hellman private key.
func (r *Ratchet) GetDHPrivateKey() *cyclic.Int {
return r.dhPrivateKey
return r.defaultDHPrivateKey
}
// GetDHPublicKey returns the diffie hellman public key.
func (r *Ratchet) GetDHPublicKey() *cyclic.Int {
return r.dhPublicKey
}
// ekv functions
func (r *Ratchet) marshal() ([]byte, error) {
contacts := make([]id.ID, len(r.managers))
index := 0
for partnerID := range r.managers {
contacts[index] = partnerID
index++
}
return json.Marshal(&contacts)
}
func (r *Ratchet) unmarshal(b []byte) error {
var contacts []id.ID
err := json.Unmarshal(b, &contacts)
if err != nil {
return err
}
for i := range contacts {
//load the contact separately to ensure pointers do not get swapped
partnerID := (&contacts[i]).DeepCopy()
// Load the relationship. The relationship handles adding the fingerprints via the
// context object
manager, err := partner.LoadManager(r.kv, r.myID, partnerID,
r.cyHandler, r.grp, r.rng)
if err != nil {
jww.FATAL.Panicf("Failed to load relationship for partner %r: %r",
partnerID, err.Error())
}
if !manager.GetPartnerID().Cmp(partnerID) {
jww.FATAL.Panicf("Loaded a manager with the wrong partner "+
"ID: \n\t loaded: %r \n\t present: %r",
partnerID, manager.GetPartnerID())
}
//add services for the manager
r.add(manager)
r.managers[*partnerID] = manager
}
r.dhPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey)
if err != nil {
return errors.WithMessage(err,
"Failed to load e2e DH private key")
}
r.dhPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey)
if err != nil {
return errors.WithMessage(err,
"Failed to load e2e DH public key")
}
return nil
return r.defaultDHPublicKey
}
......@@ -41,8 +41,8 @@ func TestNewStore(t *testing.T) {
e2eP := params.GetDefaultE2ESessionParams()
expectedStore := &Ratchet{
managers: make(map[id.ID]*partner.Manager),
dhPrivateKey: privKey,
dhPublicKey: diffieHellman.GeneratePublicKey(privKey, grp),
defaultDHPrivateKey: privKey,
defaultDHPublicKey: diffieHellman.GeneratePublicKey(privKey, grp),
grp: grp,
kv: kv.Prefix(packagePrefix),
fingerprints: &fingerprints,
......@@ -103,7 +103,7 @@ func TestStore_AddPartner(t *testing.T) {
rng := csprng.NewSystemRNG()
s, _, _ := makeTestStore()
partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t)
pubKey := diffieHellman.GeneratePublicKey(s.dhPrivateKey, s.grp)
pubKey := diffieHellman.GeneratePublicKey(s.defaultDHPrivateKey, s.grp)
p := params.GetDefaultE2ESessionParams()
// NOTE: e2e store doesn't contain a private SIDH key, that's
// because they're completely address as part of the
......@@ -111,11 +111,11 @@ func TestStore_AddPartner(t *testing.T) {
_, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA)
privSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB)
expectedManager := partner.newManager(s.context, s.kv, partnerID,
s.dhPrivateKey, pubKey,
s.defaultDHPrivateKey, pubKey,
privSIDHKey, pubSIDHKey,
p, p)
err := s.AddPartner(partnerID, pubKey, s.dhPrivateKey, pubSIDHKey,
err := s.AddPartner(partnerID, pubKey, s.defaultDHPrivateKey, pubSIDHKey,
privSIDHKey, p, p)
if err != nil {
t.Fatalf("AddPartner returned an error: %v", err)
......@@ -138,7 +138,7 @@ func TestStore_DeletePartner(t *testing.T) {
rng := csprng.NewSystemRNG()
s, _, _ := makeTestStore()
partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t)
pubKey := diffieHellman.GeneratePublicKey(s.dhPrivateKey, s.grp)
pubKey := diffieHellman.GeneratePublicKey(s.defaultDHPrivateKey, s.grp)
p := params.GetDefaultE2ESessionParams()
// NOTE: e2e store doesn't contain a private SIDH key, that's
// because they're completely address as part of the
......@@ -146,7 +146,7 @@ func TestStore_DeletePartner(t *testing.T) {
_, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA)
privSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB)
err := s.AddPartner(partnerID, pubKey, s.dhPrivateKey, pubSIDHKey,
err := s.AddPartner(partnerID, pubKey, s.defaultDHPrivateKey, pubSIDHKey,
privSIDHKey, p, p)
if err != nil {
t.Fatalf("Could not add partner in set up: %v", err)
......@@ -169,13 +169,13 @@ func TestStore_GetPartner(t *testing.T) {
rng := csprng.NewSystemRNG()
s, _, _ := makeTestStore()
partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t)
pubKey := diffieHellman.GeneratePublicKey(s.dhPrivateKey, s.grp)
pubKey := diffieHellman.GeneratePublicKey(s.defaultDHPrivateKey, s.grp)
p := params.GetDefaultE2ESessionParams()
_, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA)
privSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB)
expectedManager := partner.newManager(s.context, s.kv, partnerID,
s.dhPrivateKey, pubKey, privSIDHKey, pubSIDHKey, p, p)
_ = s.AddPartner(partnerID, pubKey, s.dhPrivateKey, pubSIDHKey,
s.defaultDHPrivateKey, pubKey, privSIDHKey, pubSIDHKey, p, p)
_ = s.AddPartner(partnerID, pubKey, s.defaultDHPrivateKey, pubSIDHKey,
privSIDHKey, p, p)
m, err := s.GetPartner(partnerID)
......@@ -209,7 +209,7 @@ func TestStore_GetPartner_Error(t *testing.T) {
func TestStore_GetPartnerContact(t *testing.T) {
s, _, _ := makeTestStore()
partnerID := id.NewIdFromUInt(rand.Uint64(), id.User, t)
pubKey := diffieHellman.GeneratePublicKey(s.dhPrivateKey, s.grp)
pubKey := diffieHellman.GeneratePublicKey(s.defaultDHPrivateKey, s.grp)
p := params.GetDefaultE2ESessionParams()
expected := contact.Contact{
ID: partnerID,
......@@ -219,7 +219,7 @@ func TestStore_GetPartnerContact(t *testing.T) {
_, pubSIDHKey := genSidhKeys(rng, sidh.KeyVariantSidhA)
privSIDHKey, _ := genSidhKeys(rng, sidh.KeyVariantSidhB)
_ = s.AddPartner(partnerID, pubKey, s.dhPrivateKey, pubSIDHKey,
_ = s.AddPartner(partnerID, pubKey, s.defaultDHPrivateKey, pubSIDHKey,
privSIDHKey, p, p)
c, err := s.GetPartnerContact(partnerID)
......@@ -307,10 +307,10 @@ func TestStore_CheckKey(t *testing.T) {
func TestStore_GetDHPrivateKey(t *testing.T) {
s, _, _ := makeTestStore()
if s.dhPrivateKey != s.GetDHPrivateKey() {
if s.defaultDHPrivateKey != s.GetDHPrivateKey() {
t.Errorf("GetDHPrivateKey() returned incorrect key."+
"\n\texpected: %v\n\treceived: %v",
s.dhPrivateKey, s.GetDHPrivateKey())
s.defaultDHPrivateKey, s.GetDHPrivateKey())
}
}
......@@ -318,10 +318,10 @@ func TestStore_GetDHPrivateKey(t *testing.T) {
func TestStore_GetDHPublicKey(t *testing.T) {
s, _, _ := makeTestStore()
if s.dhPublicKey != s.GetDHPublicKey() {
if s.defaultDHPublicKey != s.GetDHPublicKey() {
t.Errorf("GetDHPublicKey() returned incorrect key."+
"\n\texpected: %v\n\treceived: %v",
s.dhPublicKey, s.GetDHPublicKey())
s.defaultDHPublicKey, s.GetDHPublicKey())
}
}
......
package ratchet
import (
"gitlab.com/xx_network/primitives/id"
)
type relationshipIdentity [2 * id.ArrIDLen]byte
func makeRelationshipIdentity(partner, me *id.ID) relationshipIdentity {
ph := relationshipIdentity{}
copy(ph[:id.ArrIDLen], me[:])
copy(ph[id.ArrIDLen:], partner[:])
return ph
}
func (ri relationshipIdentity) GetMe() *id.ID {
me := &id.ID{}
copy(me[:], ri[:id.ArrIDLen])
return me
}
func (ri relationshipIdentity) GetPartner() *id.ID {
partner := &id.ID{}
copy(partner[:], ri[id.ArrIDLen:])
return partner
}
......@@ -19,7 +19,7 @@ func (r *Ratchet) add(m *partner.Manager) {
r.servicesmux.RLock()
defer r.servicesmux.RUnlock()
for tag, process := range r.services {
r.sInteface.AddService(r.myID, m.MakeService(tag), process)
r.sInteface.AddService(r.defaultID, m.MakeService(tag), process)
}
}
......@@ -27,7 +27,7 @@ func (r *Ratchet) delete(m *partner.Manager) {
r.servicesmux.RLock()
defer r.servicesmux.RUnlock()
for tag, process := range r.services {
r.sInteface.DeleteService(r.myID, m.MakeService(tag), process)
r.sInteface.DeleteService(r.defaultID, m.MakeService(tag), process)
}
}
......@@ -42,7 +42,7 @@ func (r *Ratchet) AddService(tag string, processor message.Processor) error {
//add a service for every manager
for _, m := range r.managers {
r.sInteface.AddService(r.myID, m.MakeService(tag), processor)
r.sInteface.AddService(r.defaultID, m.MakeService(tag), processor)
}
return nil
......@@ -61,7 +61,7 @@ func (r *Ratchet) RemoveService(tag string) error {
delete(r.services, tag)
for _, m := range r.managers {
r.sInteface.DeleteService(r.myID, m.MakeService(tag), oldServiceProcess)
r.sInteface.DeleteService(r.defaultID, m.MakeService(tag), oldServiceProcess)
}
return nil
......
package ratchet
import (
"encoding/json"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/e2e/ratchet/partner"
"gitlab.com/elixxir/client/e2e/ratchet/partner/session"
"gitlab.com/elixxir/client/network/message"
util "gitlab.com/elixxir/client/storage/utility"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/fastRNG"
"gitlab.com/elixxir/ekv"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/netTime"
)
const (
currentStoreVersion = 0
storeKey = "Store"
)
// Load loads an extant ratchet from disk
func Load(kv *versioned.KV, myID *id.ID, grp *cyclic.Group,
cyHandler session.CypherHandler, services Services, rng *fastRNG.StreamGenerator) (
*Ratchet, error) {
kv = kv.Prefix(packagePrefix)
r := &Ratchet{
managers: make(map[relationshipIdentity]*partner.Manager),
services: make(map[string]message.Processor),
defaultID: myID,
kv: kv,
memKv: versioned.NewKV(make(ekv.Memstore)),
cyHandler: cyHandler,
grp: grp,
rng: rng,
sInteface: services,
}
obj, err := kv.Get(storeKey, currentStoreVersion)
if err != nil {
//try to load an old one
obj, err = kv.Get(storeKey, 0)
if err != nil {
return nil, err
} else {
err = r.unmarshalOld(obj.Data)
if err != nil {
return nil, err
}
}
} else {
err = r.unmarshal(obj.Data)
if err != nil {
return nil, err
}
}
// add standard services
if err = r.AddService(Silent, nil); err != nil {
jww.FATAL.Panicf("Could not add standard %r "+
"service: %+v", Silent, err)
}
if err = r.AddService(E2e, nil); err != nil {
jww.FATAL.Panicf("Could not add standard %r "+
"service: %+v", E2e, err)
}
return r, nil
}
func (r *Ratchet) save() error {
now := netTime.Now()
data, err := r.marshal()
if err != nil {
return err
}
obj := versioned.Object{
Version: currentStoreVersion,
Timestamp: now,
Data: data,
}
return r.kv.Set(storeKey, currentStoreVersion, &obj)
}
// ekv functions
func (r *Ratchet) marshal() ([]byte, error) {
contacts := make([]relationshipIdentity, len(r.managers))
index := 0
for rid, m := range r.managers {
if !m.IsTemporary() {
contacts[index] = rid
index++
}
}
return json.Marshal(&contacts)
}
// In the event an old structure was loaded, unmarshal it and upgrade it
func (r *Ratchet) unmarshalOld(b []byte) error {
var contacts []id.ID
err := json.Unmarshal(b, &contacts)
if err != nil {
return err
}
for i := range contacts {
//load the contact separately to ensure pointers do not get swapped
partnerID := (&contacts[i]).DeepCopy()
// Load the relationship. The relationship handles adding the fingerprints via the
// context object
manager, err := partner.LoadManager(r.kv, r.defaultID, partnerID,
r.cyHandler, r.grp, r.rng)
if err != nil {
jww.FATAL.Panicf("Failed to load relationship for partner %r: %r",
partnerID, err.Error())
}
if !manager.GetPartnerID().Cmp(partnerID) {
jww.FATAL.Panicf("Loaded a manager with the wrong partner "+
"ID: \n\t loaded: %r \n\t present: %r",
partnerID, manager.GetPartnerID())
}
//add services for the manager
r.add(manager)
//assume
r.managers[makeRelationshipIdentity(partnerID, r.defaultID)] = manager
}
r.defaultDHPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey)
if err != nil {
return errors.WithMessage(err,
"Failed to load e2e DH private key")
}
r.defaultDHPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey)
if err != nil {
return errors.WithMessage(err,
"Failed to load e2e DH public key")
}
return nil
}
func (r *Ratchet) unmarshal(b []byte) error {
var contacts []relationshipIdentity
err := json.Unmarshal(b, &contacts)
if err != nil {
return err
}
for i := range contacts {
//load the contact separately to ensure pointers do not get swapped
partnerID := contacts[i].GetPartner()
myID := contacts[i].GetMe()
// Load the relationship. The relationship handles adding the fingerprints via the
// context object
manager, err := partner.LoadManager(r.kv, myID, partnerID,
r.cyHandler, r.grp, r.rng)
if err != nil {
jww.FATAL.Panicf("Failed to load relationship for partner %r: %r",
partnerID, err.Error())
}
if !manager.GetPartnerID().Cmp(partnerID) {
jww.FATAL.Panicf("Loaded a manager with the wrong partner "+
"ID: \n\t loaded: %r \n\t present: %r",
partnerID, manager.GetPartnerID())
}
//add services for the manager
r.add(manager)
r.managers[contacts[i]] = manager
}
r.defaultDHPrivateKey, err = util.LoadCyclicKey(r.kv, privKeyKey)
if err != nil {
return errors.WithMessage(err,
"Failed to load e2e DH private key")
}
r.defaultDHPublicKey, err = util.LoadCyclicKey(r.kv, pubKeyKey)
if err != nil {
return errors.WithMessage(err,
"Failed to load e2e DH public key")
}
return nil
}
......@@ -36,12 +36,13 @@ func handleConfirm(ratchet *ratchet.Ratchet, confirmation receive.Message) {
if !confirmation.Encrypted {
jww.ERROR.Printf(
"[REKEY] Received non-e2e encrypted Key Exchange "+
"confirm from partner %s", confirmation.Sender)
"confirm from partner %s to %s", confirmation.Sender,
confirmation.RecipientID)
return
}
//get the partner
partner, err := ratchet.GetPartner(confirmation.Sender)
partner, err := ratchet.GetPartner(confirmation.Sender, confirmation.RecipientID)
if err != nil {
jww.ERROR.Printf(
"[REKEY] Received Key Exchange Confirmation with unknown "+
......
......@@ -61,7 +61,7 @@ func handleTrigger(ratchet *ratchet.Ratchet, sender E2eSender,
}
//get the partner
partner, err := ratchet.GetPartner(request.Sender)
partner, err := ratchet.GetPartner(request.Sender, request.RecipientID)
if err != nil {
errMsg := fmt.Sprintf(errUnknown, request.Sender)
jww.ERROR.Printf(errMsg)
......
......@@ -64,7 +64,7 @@ func (m *manager) sendUnsafe(mt catalog.MessageType, recipient *id.ID,
wg.Add(1)
go func(i int, payload []byte) {
unencryptedMAC, fp := e2e.SetUnencrypted(payload, m.myID)
unencryptedMAC, fp := e2e.SetUnencrypted(payload, m.myDefaultID)
var err error
roundIds[i], _, err = m.net.SendCMIX(recipient, fp,
......
package utility
import (
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/netTime"
)
const currentIDVersion = 0
func StoreID(kv *versioned.KV, sid *id.ID, key string) error {
now := netTime.Now()
data, err := sid.MarshalJSON()
if err != nil {
return err
}
obj := versioned.Object{
Version: currentIDVersion,
Timestamp: now,
Data: data,
}
return kv.Set(key, currentIDVersion, &obj)
}
func LoadID(kv *versioned.KV, key string) (*id.ID, error) {
vo, err := kv.Get(key, currentIDVersion)
if err != nil {
return nil, err
}
sid := &id.ID{}
return sid, sid.UnmarshalJSON(vo.Data)
}
// DeleteCID deletes a given cyclic key from storage
func DeleteCID(kv *versioned.KV, key string) error {
return kv.Delete(key, currentIDVersion)
}
......@@ -151,6 +151,11 @@ func (v *KV) Prefix(prefix string) *KV {
return &kvPrefix
}
func (v *KV) IsMemStore() bool {
_, success := v.r.data.(ekv.Memstore)
return success
}
//Returns the key with all prefixes appended
func (v *KV) GetFullKey(key string, version uint64) string {
return v.makeKey(key, version)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment