diff --git a/Makefile b/Makefile
index 9c16bd45cb615fabfce834ad0a8e2cdf5518218d..a11b087948ddc0b6a076a585e7eaa61f2e19f16d 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ build:
 
 update_release:
 	GOFLAGS="" go get -u gitlab.com/elixxir/primitives@release
-	GOFLAGS="" go get -u gitlab.com/elixxir/crypto@release
+	GOFLAGS="" go get -u gitlab.com/elixxir/crypto@ben/newE2E
 	GOFLAGS="" go get -u gitlab.com/elixxir/comms@release
 	GOFLAGS="" go get -u gitlab.com/xx_network/comms@release
 	GOFLAGS="" go get -u gitlab.com/xx_network/primitives@release	
diff --git a/go.mod b/go.mod
index dd4027a2473bb8aef8db64504fa537c4d9fc5c4b..ecae5105ff729de19564b50d63594052c7318bbe 100644
--- a/go.mod
+++ b/go.mod
@@ -15,12 +15,13 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/spf13/viper v1.6.2
-	gitlab.com/elixxir/comms v0.0.0-20200805174832-240bba97beaa
-	gitlab.com/elixxir/crypto v0.0.0-20200805174804-bdf909f2a16d
+	gitlab.com/elixxir/comms v0.0.0-20200813225502-e879259ca741
+	gitlab.com/elixxir/crypto v0.0.0-20200819000020-020937ea25db
 	gitlab.com/elixxir/ekv v0.1.1
-	gitlab.com/elixxir/primitives v0.0.0-20200805174810-86b366d1dd2d
-	gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023
-	gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da
+	gitlab.com/elixxir/primitives v0.0.0-20200812191102-31c01f08b4dc
+	gitlab.com/xx_network/comms v0.0.0-20200818182121-732dd75b1947
+	gitlab.com/xx_network/primitives v0.0.0-20200812183720-516a65a4a9b2
+	gitlab.com/xx_network/ring v0.0.2
 	golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
 	golang.org/x/sys v0.0.0-20200806125547-5acd03effb82 // indirect
 	gopkg.in/ini.v1 v1.52.0 // indirect
diff --git a/go.sum b/go.sum
index 6daefd75f3b24c3ed997c6c6a0ac1ae451d6a170..3e57ab4c7033015540645942bd55b105a71aa0ef 100644
--- a/go.sum
+++ b/go.sum
@@ -163,12 +163,19 @@ github.com/zeebo/blake3 v0.0.4/go.mod h1:YOZo8A49yNqM0X/Y+JmDUZshJWLt1laHsNSn5ny
 github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm//LBaEvBiaXY7hXJ6KGe2V32X2F6E=
 gitlab.com/elixxir/comms v0.0.0-20200805174832-240bba97beaa h1:yn5FW/zPPKb0DYbN1HvhudYkCrXhpBK4CrZGeUKCGu4=
 gitlab.com/elixxir/comms v0.0.0-20200805174832-240bba97beaa/go.mod h1:Wc6fZyP/M4sBjnzb9pRScLeqwMOCv6DRXoTOd07bO3g=
+gitlab.com/elixxir/comms v0.0.0-20200813225502-e879259ca741 h1:yIjgre8xSDpnhJkDzTr1lgR7NC1bPWCk2Sgn8udiS2A=
+gitlab.com/elixxir/comms v0.0.0-20200813225502-e879259ca741/go.mod h1:hEi6dhcR1v6TGcp3tBy+QFuE25zux206xymuB+PpUqs=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4 h1:28ftZDeYEko7xptCZzeFWS1Iam95dj46TWFVVlKmw6A=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
 gitlab.com/elixxir/crypto v0.0.0-20200805174804-bdf909f2a16d h1:3+o6r8a0o9/HIpBzlGCCiwuPN8OdEX3cHzdnCNqKDAw=
 gitlab.com/elixxir/crypto v0.0.0-20200805174804-bdf909f2a16d/go.mod h1:cu6uNoANVLV0J6HyTL6KqVtVyh9SHU1RjJhytYlsbVQ=
+gitlab.com/elixxir/crypto v0.0.0-20200806211835-b8ce4472f399/go.mod h1:LthCESQ1AfV1H26URYL9kr+XgXXCE7JfEEPpomFPxIo=
+gitlab.com/elixxir/crypto v0.0.0-20200811195343-de268a55c7c4/go.mod h1:LthCESQ1AfV1H26URYL9kr+XgXXCE7JfEEPpomFPxIo=
+gitlab.com/elixxir/crypto v0.0.0-20200819000020-020937ea25db h1:1TWIk/c0FOUc2uVxEodkkKlig4ZRHMODBLMoW/r2kxU=
+gitlab.com/elixxir/crypto v0.0.0-20200819000020-020937ea25db/go.mod h1:SpcmFZ4baOMRxH7qo2myvYFNr8/bz9ItYzVo5Q2Ld1k=
 gitlab.com/elixxir/ekv v0.1.1 h1:Em3rF8sv+tNbQGXbcpYzAS2blWRAP708JGhYlkN74Kg=
 gitlab.com/elixxir/ekv v0.1.1/go.mod h1:bXY0kgbV5BHYda4YY5/hiG5bjimGK+R3PYub5yM9C/s=
+gitlab.com/elixxir/primitives v0.0.0-20200608222556-1d2c04e59346/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d h1:OKWTmYN5q8XVHo8JXThIH0TCuvl/fLXR7MGVacpqfRg=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
 gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9 h1:o0P00afLOlI3/98DR3G5IfGSTAO1ab/uzhPYzxE/Kcg=
@@ -178,13 +185,23 @@ gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFF
 gitlab.com/elixxir/primitives v0.0.0-20200804231232-ad79a9e8f113/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=
 gitlab.com/elixxir/primitives v0.0.0-20200805174810-86b366d1dd2d h1:ky5oz0D2EmOzk2n/A6Ugwj7S1B6rftxMJwc19sjGkz8=
 gitlab.com/elixxir/primitives v0.0.0-20200805174810-86b366d1dd2d/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=
+gitlab.com/elixxir/primitives v0.0.0-20200812191102-31c01f08b4dc h1:43innow2sbJLflB73gwS8gg1meInFXNA1LGYeeDQ6lw=
+gitlab.com/elixxir/primitives v0.0.0-20200812191102-31c01f08b4dc/go.mod h1:pJx2DZk9s8vVMnLN7x0hIPngDjbNSdOP6kk3RLlRxHg=
 gitlab.com/xx_network/comms v0.0.0-20200804225654-09a9af23d699 h1:e9rzUjMxt/4iQ5AVXVgwANvbgxxXgWEbvApgd6P72jU=
 gitlab.com/xx_network/comms v0.0.0-20200804225654-09a9af23d699/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw=
 gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023 h1:fQPaxyuXyH3vl8qFlFDBEx8rlEzBnXBNy74K8ItFRM4=
 gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw=
+gitlab.com/xx_network/comms v0.0.0-20200812204124-8dc2a2a1b9ca/go.mod h1:idLzPGYig57XE7xuU93OlIF9s6NgSJj7OArQvsd5DjY=
+gitlab.com/xx_network/comms v0.0.0-20200818182121-732dd75b1947 h1:g0k4nP0o/6qkh09F9d/Fy7Ys93fkyZU+kK71JviLdMg=
+gitlab.com/xx_network/comms v0.0.0-20200818182121-732dd75b1947/go.mod h1:idLzPGYig57XE7xuU93OlIF9s6NgSJj7OArQvsd5DjY=
+gitlab.com/xx_network/crypto v0.0.0-20200806202113-978fa1984bbf/go.mod h1:i0df/q6dDCBiscgD51fMoS2U2TBrm6LcyN822JmB5Tw=
+gitlab.com/xx_network/crypto v0.0.0-20200806235322-ede3c15881ce h1:gypNBUl2guESEv4MDgH+miwYqR4jPoWM8dLt2Zs5gIs=
+gitlab.com/xx_network/crypto v0.0.0-20200806235322-ede3c15881ce/go.mod h1:i0df/q6dDCBiscgD51fMoS2U2TBrm6LcyN822JmB5Tw=
 gitlab.com/xx_network/primitives v0.0.0-20200803231956-9b192c57ea7c/go.mod h1:wtdCMr7DPePz9qwctNoAUzZtbOSHSedcK++3Df3psjA=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da h1:CCVslUwNC7Ul7NG5nu3ThGTSVUt1TxNRX+47f5TUwnk=
 gitlab.com/xx_network/primitives v0.0.0-20200804183002-f99f7a7284da/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug=
+gitlab.com/xx_network/primitives v0.0.0-20200812183720-516a65a4a9b2 h1:Jvv2fLk+2ULDCXiVTPI8Jlg2fBrmq2NSA+dlsN5t2Pk=
+gitlab.com/xx_network/primitives v0.0.0-20200812183720-516a65a4a9b2/go.mod h1:OK9xevzWCaPO7b1wiluVJGk7R5ZsuC7pHY5hteZFQug=
 gitlab.com/xx_network/ring v0.0.2 h1:TlPjlbFdhtJrwvRgIg4ScdngMTaynx/ByHBRZiXCoL0=
 gitlab.com/xx_network/ring v0.0.2/go.mod h1:aLzpP2TiZTQut/PVHR40EJAomzugDdHXetbieRClXIM=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
diff --git a/key/context.go b/key/context.go
new file mode 100644
index 0000000000000000000000000000000000000000..1d7ac802a439f08a502fa4a7db4efa173b729a67
--- /dev/null
+++ b/key/context.go
@@ -0,0 +1,14 @@
+package key
+
+import (
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/crypto/cyclic"
+)
+
+type context struct {
+	fa fingerprintAccess
+
+	grp *cyclic.Group
+
+	kv *storage.Session
+}
diff --git a/key/fingerprintAccess.go b/key/fingerprintAccess.go
index b519a915000610a3846b5e17ae85e3c53bb7347b..5868760902621ae41a353e2360e83ebaa35f99cd 100644
--- a/key/fingerprintAccess.go
+++ b/key/fingerprintAccess.go
@@ -1,7 +1,8 @@
 package key
 
-type FingerprintAccess interface {
-	AddFingerprints([]*Key) error
-	//recieves a list of fingerprints
-	RemoveFingerprints([]*Key) error
+type fingerprintAccess interface {
+	// Receives a list of fingerprints to add. Overrides on collision.
+	add([]*Key)
+	// Receives a list of fingerprints to delete. Ignores any not available Keys
+	remove([]*Key)
 }
diff --git a/key/key.go b/key/key.go
index 283f1912322a616a67b65b0dd74de44e8bf278ee..66395e39ac88c7209805b2223905f160c07d6d72 100644
--- a/key/key.go
+++ b/key/key.go
@@ -1,18 +1,19 @@
 package key
 
 import (
+	"github.com/pkg/errors"
 	"gitlab.com/elixxir/client/parse"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/hash"
 	"gitlab.com/elixxir/primitives/format"
+	jww "github.com/spf13/jwalterweatherman"
 )
 
 type Key struct {
 	// Links
 	session *Session
 
-	// Key to be used
-	key *cyclic.Int
+	fp *format.Fingerprint
 
 	// Designation of crypto type
 	outer parse.CryptoType
@@ -22,7 +23,14 @@ type Key struct {
 	keyNum uint32
 }
 
-func Operate(func(s *Session, )) error
+func newKey(session *Session, key *cyclic.Int, outer parse.CryptoType, keynum uint32) *Key {
+	return &Key{
+		session: session,
+		key:     key,
+		outer:   outer,
+		keyNum:  keynum,
+	}
+}
 
 // return pointers to higher level management structures
 func (k *Key) GetSession() *Session { return k.session }
@@ -36,10 +44,30 @@ func (k *Key) GetOuterType() parse.CryptoType { return k.outer }
 // Generate key fingerprint
 // NOTE: This function is not a getter,
 // it returns a new byte array on each call
-func (k *Key) KeyFingerprint() format.Fingerprint {
+func (k *Key) Fingerprint() format.Fingerprint {
 	h, _ := hash.NewCMixHash()
 	h.Write(k.key.Bytes())
 	fp := format.Fingerprint{}
 	copy(fp[:], h.Sum(nil))
 	return fp
 }
+
+// Sets the key as used
+func (k *Key) denoteUse() error {
+	switch k.outer {
+	case parse.E2E:
+		err := k.session.useKey(k.keyNum)
+		if err != nil {
+			return errors.WithMessage(err, "Could not use e2e key")
+		}
+
+	case parse.Rekey:
+		err := k.session.useReKey(k.keyNum)
+		if err != nil {
+			return errors.WithMessage(err, "Could not use e2e rekey")
+		}
+	default:
+		jww.FATAL.Panicf("Key has invalid cryptotype: %s", k.outer)
+	}
+	return nil
+}
\ No newline at end of file
diff --git a/key/manager.go b/key/manager.go
index 2620f4d7d3b8de8cface1d590bb159f243579374..af241d19f5c74803166cbc643f05445df4318aeb 100644
--- a/key/manager.go
+++ b/key/manager.go
@@ -1,44 +1,142 @@
 package key
 
 import (
+	"github.com/pkg/errors"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/xx_network/primitives/id"
 )
 
 type Manager struct {
-	params Params
+	ctx *context
 
-	partner id.ID
+	partner *id.ID
 
-	receive *SessionBuff
-	send    *SessionBuff
+	receive *sessionBuff
+	send    *sessionBuff
 }
 
-// generator
-func NewManager(params Params, partnerID *id.ID, myPrivKey *cyclic.Int, partnerPubKey *cyclic.Int) (*Manager, error) {
-	return nil, nil
+// create the manager and its first send and receive sessions
+func newManager(ctx *context, partnerID *id.ID, myPrivKey *cyclic.Int,
+	partnerPubKey *cyclic.Int, sendParams, receiveParams SessionParams) (*Manager, error) {
+	m := &Manager{
+		ctx:     ctx,
+		partner: partnerID,
+	}
+
+	m.send = NewSessionBuff(m, "send")
+	m.receive = NewSessionBuff(m, "receive")
+
+	sendSession, err := newSession(m, myPrivKey, partnerPubKey, sendParams, true)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to create the send session")
+	}
+
+	err = m.send.AddSession(sendSession)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to add the send session to buffer")
+	}
+
+	receiveSession, err := newSession(m, myPrivKey, partnerPubKey, receiveParams, true)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to create the receive session")
+	}
+
+	err = m.receive.AddSession(receiveSession)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to add the receive session to buffer")
+	}
+
+	return m, nil
 }
 
-// ekv functions
-func (m *Manager) Marshal() ([]byte, error) { return nil, nil }
-func (m *Manager) Unmarshal([]byte) error   { return nil }
+//loads a manager and all buffers and sessions from disk
+func loadManager(ctx *context, partnerID *id.ID) (*Manager, error) {
+	m := &Manager{
+		ctx:     ctx,
+		partner: partnerID,
+	}
+
+	var err error
+
+	m.send, err = LoadSessionBuff(m, "send", partnerID)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to load partner key manager due to failure to "+
+				"load the send session buffer")
+	}
+
+	m.receive, err = LoadSessionBuff(m, "receive", partnerID)
+	if err != nil {
+		return nil, errors.WithMessage(err,
+			"Failed to load partner key manager due to failure to "+
+				"load the receive session buffer")
+	}
+
+	return m, nil
+}
 
 //gets a copy of the ID of the partner
-func (m *Manager) GetPartner() *id.ID {
+func (m *Manager) GetPartnerID() *id.ID {
 	p := m.partner
-	return &p
+	return p
 }
 
 // creates a new receive session using the latest private key this user has sent
-// and the new public key received from the partner
-func (m *Manager) NewReceiveSession(partnerPubKey *cyclic.Int) {}
+// and the new public key received from the partner.
+func (m *Manager) NewReceiveSession(partnerPubKey *cyclic.Int, params SessionParams) error {
+	//find your last confirmed private key
+	myPrivKey := m.send.GetNewestConfirmed().GetMyPrivKey()
+
+	//create the session
+	session, err := newSession(m, myPrivKey, partnerPubKey, params, true)
+
+	if err != nil {
+		return err
+	}
+
+	//add the session to the buffer
+	err = m.receive.AddSession(session)
+	if err != nil {
+		//delete the session if it failed to add to the buffer
+		err = session.Delete()
+	}
+
+	return err
+}
 
 // creates a new receive session using the latest public key received from the
 // partner and a mew private key for the user
-func (m *Manager) NewSendSession(myPrivKey *cyclic.Int) {}
+// passing in a private key is optional. a private key will be generated if
+// none is passed
+func (m *Manager) NewSendSession(myPrivKey *cyclic.Int, params SessionParams) error {
+	//find the latest public key from the other party
+	partnerPubKey := m.receive.GetNewestConfirmed().partnerPubKey
 
-// gets the session buffer for message reception
-func (m *Manager) GetReceiveSessionBuff() *SessionBuff { return nil }
+	session, err := newSession(m, myPrivKey, partnerPubKey, params, false)
+	if err != nil {
+		return err
+	}
+
+	//add the session to the buffer
+	err = m.send.AddSession(session)
+	if err != nil {
+		//delete the session if it failed to add to the buffer
+		err = session.Delete()
+	}
+
+	return err
+}
 
 // gets the session buffer for message reception
-func (m *Manager) LatestReceiveSession() *Session { return nil }
+func (m *Manager) GetSendingSession() *Session {
+	return m.send.GetSessionForSending()
+}
+
+// Confirms a send session is known about by the partner
+func (m *Manager) Confirm(sid SessionID) error {
+	return m.send.Confirm(sid)
+}
diff --git a/key/params.go b/key/params.go
index fed96b5da812ff4e8567b7d87cf2e2dc26588791..d8c62be1241dbc1a77f0f1e186983202cccd5a81 100644
--- a/key/params.go
+++ b/key/params.go
@@ -20,15 +20,15 @@ const (
 	numReKeys uint16  = 64
 )
 
-type Params struct {
+type SessionParams struct {
 	MinKeys   uint16
 	MaxKeys   uint16
 	NumRekeys uint16
 	e2e.TTLParams
 }
 
-func GetDefaultParams() Params {
-	return Params{
+func GetDefaultSessionParams() SessionParams {
+	return SessionParams{
 		MinKeys:   minKeys,
 		MaxKeys:   maxKeys,
 		NumRekeys: numReKeys,
@@ -37,4 +37,4 @@ func GetDefaultParams() Params {
 			MinNumKeys: threshold,
 		},
 	}
-}
+}
\ No newline at end of file
diff --git a/key/session.go b/key/session.go
index b8f70249715b21db678e7224b35f6d0f093d5cc1..154e9332773ccfb7f6e62a81bbd5cfeb9dbf47aa 100644
--- a/key/session.go
+++ b/key/session.go
@@ -1,22 +1,25 @@
 package key
 
 import (
-	"encoding/base64"
-	"gitlab.com/elixxir/client/keyStore"
+	"encoding/json"
+	"gitlab.com/elixxir/client/storage"
 	"gitlab.com/elixxir/crypto/cyclic"
+	"gitlab.com/elixxir/crypto/diffieHellman"
 	"gitlab.com/elixxir/crypto/hash"
 	"sync"
+	"time"
 )
 
-type SessionID [32]byte
-
-func (sid SessionID) String() string {
-	return base64.StdEncoding.EncodeToString(sid[:])
-}
+const currentSessionVersion = 0
 
 type Session struct {
 	//pointer to manager
 	manager *Manager
+	//params
+	params SessionParams
+
+	//type
+	t SessionType
 
 	// Underlying key
 	baseKey *cyclic.Int
@@ -29,76 +32,129 @@ type Session struct {
 	confirmed bool
 
 	// Value of the counter at which a rekey is triggered
-	ttl uint16
-
-	// Total number of Keys
-	numKeys uint32
-	// Total number of Rekey keys
-	numReKeys uint16
+	ttl uint32
 
 	// Received Keys dirty bits
 	// Each bit represents a single Key
-	KeyState []*uint64
+	keyState *stateVector
 	// Received ReKeys dirty bits
 	// Each bit represents a single ReKey
-	ReKeyState []*uint64
-
-	// Keys
-	keys    []*Key
-	lastKey uint32
-
-	// ReKeys
-	reKeys    []*Key
-	lastReKey uint32
+	reKeyState *stateVector
 
 	//mutex
 	mux sync.RWMutex
 }
 
 type SessionDisk struct {
+	params SessionParams
+
 	// Underlying key
-	baseKey *cyclic.Int
+	BaseKey []byte
 	// Own Private Key
-	myPrivKey *cyclic.Int
+	MyPrivKey []byte
 	// Partner Public Key
-	partnerPubKey *cyclic.Int
-
-	// Received Keys dirty bits
-	// Each bit represents a single Key
-	KeyState []*uint64
-	// Received ReKeys dirty bits
-	// Each bit represents a single ReKey
-	ReKeyState []*uint64
+	PartnerPubKey []byte
 
 	//denotes if the other party has confirmed this key
-	confirmed bool
-
-	//position of the earliest unused key
-	lastKey uint32
+	Confirmed bool
+}
 
-	//position of the earliest unused key
-	lastReKey uint32
+/*CONSTRUCTORS*/
+//Generator which creates all keys and structures
+func newSession(manager *Manager, myPrivKey *cyclic.Int, partnerPubKey *cyclic.Int, params SessionParams, t SessionType) (*Session, error) {
+	session := &Session{
+		params:        params,
+		manager:       manager,
+		t:             t,
+		myPrivKey:     myPrivKey,
+		partnerPubKey: partnerPubKey,
+		confirmed:     t == Receive,
+	}
+
+	err := session.generateKeys()
+	if err != nil {
+		return nil, err
+	}
+
+	err = session.save()
+	if err != nil {
+		return nil, err
+	}
+
+	return session, nil
 }
 
 //Generator which creates all keys and structures
-func (s *Session) NewSession(myPrivKey *cyclic.Int, partnerPubKey *cyclic.Int, manager *Manager) (*Session, error) {
-	return nil, nil
+func loadSession(manager *Manager, key string) (*Session, error) {
+
+	session := Session{
+		manager: manager,
+	}
+
+	obj, err := manager.ctx.kv.Get(key)
+	if err != nil {
+		return nil, err
+	}
+
+	err = session.unmarshal(obj.Data)
+	if err != nil {
+		return nil, err
+	}
+
+	return &session, nil
 }
 
-//Gets the manager used to
+func (s *Session) save() error {
+	key := makeSessionKey(s.GetID())
+
+	now, err := time.Now().MarshalText()
+	if err != nil {
+		return err
+	}
+
+	data, err := s.marshal()
+	if err != nil {
+		return err
+	}
+
+	obj := storage.VersionedObject{
+		Version:   currentSessionVersion,
+		Timestamp: now,
+		Data:      data,
+	}
+
+	return s.manager.ctx.kv.Set(key, &obj)
+}
+
+/*METHODS*/
+func (s *Session) Delete() error {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	s.manager.ctx.fa.remove(s.keys)
+	s.manager.ctx.fa.remove(s.reKeys)
+
+	return s.manager.ctx.kv.Delete(makeSessionKey(s.GetID()))
+}
 
 //Gets the base key.
 func (s *Session) GetBaseKey() *cyclic.Int {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
 	// no lock is needed because this cannot be edited
 	return s.baseKey.DeepCopy()
 }
 
 func (s *Session) GetMyPrivKey() *cyclic.Int {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
 	// no lock is needed because this cannot be edited
 	return s.myPrivKey.DeepCopy()
 }
 
 func (s *Session) GetPartnerPubKey() *cyclic.Int {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
 	// no lock is needed because this cannot be edited
 	return s.partnerPubKey.DeepCopy()
 }
@@ -113,41 +169,138 @@ func (s *Session) GetID() SessionID {
 }
 
 //ekv functions
-func (s *Session) Marshal() ([]byte, error) { return nil, nil }
-func (s *Session) Unmarshal([]byte) error   { return nil }
+func (s *Session) marshal() ([]byte, error) {
+	sd := SessionDisk{}
+
+	sd.params = s.params
+	sd.BaseKey = s.baseKey.Bytes()
+	sd.MyPrivKey = s.myPrivKey.Bytes()
+	sd.PartnerPubKey = s.partnerPubKey.Bytes()
+	sd.Confirmed = s.confirmed
+
+	return json.Marshal(&sd)
+}
+
+func (s *Session) unmarshal(b []byte) error {
+
+	sd := SessionDisk{}
+
+	err := json.Unmarshal(b, &sd)
+
+	if err != nil {
+		return err
+	}
+
+	grp := s.manager.ctx.grp
+
+	s.params = sd.params
+	s.baseKey = grp.NewIntFromBytes(sd.BaseKey)
+	s.myPrivKey = grp.NewIntFromBytes(sd.MyPrivKey)
+	s.partnerPubKey = grp.NewIntFromBytes(sd.PartnerPubKey)
+	s.confirmed = sd.Confirmed
+
+	sid := s.GetID()
+
+	s.keyState, err = loadStateVector(s.manager.ctx, makeStateVectorKey("keyStates", sid))
+	if err != nil {
+		return err
+	}
+
+	s.reKeyState, err = loadStateVector(s.manager.ctx, makeStateVectorKey("reKeyStates", sid))
+	if err != nil {
+		return err
+	}
+
+	return s.generateKeys()
+}
 
 //key usage
-// Pops the first unused key, skipping any which are denoted as used
-func (s *Session) PopKey() (*keyStore.E2EKey, error) { return nil, nil }
+// Pops the first unused key, skipping any which are denoted as used. The status
+// is returned to check if a rekey is nessessary
+func (s *Session) PopKey() (*Key, error) {
+	keynum, err := s.keyState.Next()
+	if err != nil {
+		return nil, err
+	}
+
+	return s.keys[keynum], nil
+}
 
 // Pops the first unused rekey, skipping any which are denoted as used
-func (s *Session) PopReKey() (*keyStore.E2EKey, error) { return nil, nil }
-
-// denotes the passed key as used
-func (s *Session) UseKey(*keyStore.E2EKey) error { return nil }
+func (s *Session) PopReKey() (*Key, error) {
+	keynum, err := s.reKeyState.Next()
+	if err != nil {
+		return nil, err
+	}
+	return s.reKeys[keynum], nil
+}
 
-// denotes the passed rekey as used
-func (s *Session) UseRekey(*keyStore.E2EKey) error { return nil }
+// returns the state of the session, which denotes if the Session is active,
+// functional but in need of a rekey, empty of send key, or empty of rekeys
+func (s *Session) Status() Status {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	if s.reKeyState.GetNumKeys() == 0 {
+		return RekeyEmpty
+	} else if s.keyState.GetNumKeys() == 0 {
+		return Empty
+	} else if s.keyState.GetNumKeys() >= s.ttl {
+		return RekeyNeeded
+	} else {
+		return Active
+	}
+}
 
-// returns the state of the keyblob, which denotes if the Session is active,
+// returns the state of the session, which denotes if the Session is active,
 // functional but in need of a rekey, empty of send key, or empty of rekeys
-func (s *Session) Status() Status { return 0 }
+func (s *Session) IsReKeyNeeded() bool {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.keyState.GetNumAvailable() == s.ttl
+}
+
+// checks if the session has been confirmed
+func (s *Session) IsConfirmed() bool {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+	return s.confirmed
+}
+
+/*PRIVATE*/
 
 // Sets the confirm bool. this is set when the partner is certain to share the
 // session. It should be called immediately for receive keys and only on rekey
 // confirmation for send keys. Confirmation can only be made by the sessionBuffer
 // because it is used to keep track of active sessions for rekey as well
-func (s *Session) confirm() {
+func (s *Session) confirm() error {
 	s.mux.Lock()
 	defer s.mux.Unlock()
 	s.confirmed = true
+	return s.save()
 }
 
-// checks if the session has been confirmed
-func (s *Session) IsConfirmed() bool {
-	s.mux.RLock()
-	defer s.mux.RUnlock()
-	return s.confirmed
+func (s *Session) useKey(keynum uint32) error {
+	return s.keyState.Use(keynum)
 }
 
-/*PRIVATE*/
+func (s *Session) useReKey(keynum uint32) error {
+	return s.reKeyState.Use(keynum)
+}
+
+// generates keys from the base data stored in the session object.
+// required fields: partnerPubKey, confirmed, manager, grp
+// myPrivKey, baseKey, keyState, and ReKeyState will be
+// created/calculated if not present
+// if keyState is not present lastKey will be ignored and set to zero
+// if ReKeyState is not present lastReKey will be ignored and set to zero
+func (s *Session) generateKeys() error {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	//if not private key is present, generate one
+	if s.myPrivKey == nil {
+		s.myPrivKey, diffieHellman
+	}
+
+	return nil
+}
\ No newline at end of file
diff --git a/key/sessionBuff.go b/key/sessionBuff.go
index 6ba97f8a0b1b400771fe87ef57b8b60d34f4e380..ea6b4bc2096b69e82ea10764dc34e88e30273ffb 100644
--- a/key/sessionBuff.go
+++ b/key/sessionBuff.go
@@ -1,37 +1,139 @@
 package key
 
 import (
+	"encoding/base64"
+	"encoding/json"
 	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/xx_network/primitives/id"
 	"sync"
+	jww "github.com/spf13/jwalterweatherman"
+	"time"
 )
 
-type SessionBuff struct {
+const maxUnconfirmed uint = 3
+const currentSessionBuffVersion = 0
+
+type sessionBuff struct {
+	manager *Manager
+
 	sessions    []*Session
 	sessionByID map[SessionID]*Session
 
+	keyPrefix string
+
 	mux sync.RWMutex
 }
 
-type SessionBuffDisk struct {
-	sessions []SessionID
+func NewSessionBuff(manager *Manager, keyPrefix string) *sessionBuff {
+	return &sessionBuff{
+		manager:     manager,
+		sessions:    make([]*Session, 0),
+		sessionByID: make(map[SessionID]*Session),
+		mux:         sync.RWMutex{},
+		keyPrefix:   keyPrefix,
+	}
+}
+
+func LoadSessionBuff(manager *Manager, keyPrefix string, partnerID *id.ID) (*sessionBuff, error) {
+	sb := &sessionBuff{
+		manager:     manager,
+		sessionByID: make(map[SessionID]*Session),
+		mux:         sync.RWMutex{},
+	}
+
+	key := makeSessionBuffKey(keyPrefix, partnerID)
+
+	obj, err := manager.ctx.kv.Get(key)
+	if err != nil {
+		return nil, err
+	}
+
+	err = sb.unmarshal(obj.Data)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return sb, nil
 }
 
-func NewSessionBuff(n int, deletion func(session *Session)) *SessionBuff { return &SessionBuff{} }
+func (sb *sessionBuff) save() error {
+	key := makeSessionBuffKey(sb.keyPrefix, sb.manager.partner)
+
+	now, err := time.Now().MarshalText()
+	if err != nil {
+		return err
+	}
+
+	data, err := sb.marshal()
+	if err != nil {
+		return err
+	}
+
+	obj := storage.VersionedObject{
+		Version:   currentSessionBuffVersion,
+		Timestamp: now,
+		Data:      data,
+	}
+
+	return sb.manager.ctx.kv.Set(key, &obj)
+}
 
 //ekv functions
-func (sb *SessionBuff) Marshal() ([]byte, error) { return nil, nil }
-func (sb *SessionBuff) Unmarshal([]byte) error   { return nil }
+func (sb *sessionBuff) marshal() ([]byte, error) {
+	sessions := make([]SessionID, len(sb.sessions))
+
+	index := 0
+	for sid := range sb.sessionByID {
+		sessions[index] = sid
+		index++
+	}
+
+	return json.Marshal(&sessions)
+}
+
+func (sb *sessionBuff) unmarshal(b []byte) error {
+	var sessions []SessionID
+
+	err := json.Unmarshal(b, &sessions)
 
-func (sb *SessionBuff) AddSession(s *Session) {
+	if err != nil {
+		return err
+	}
+
+	sb.sessions = make([]*Session, len(sessions))
+
+	//load all the sessions
+	for _, sid := range sessions {
+		key := makeSessionKey(sid)
+		session, err := loadSession(sb.manager, key)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to load session %s for %s: %s",
+				key, sb.manager.partner, err.Error())
+		}
+		sb.addSession(session)
+	}
+
+	return nil
+}
+
+func (sb *sessionBuff) AddSession(s *Session) error {
 	sb.mux.Lock()
 	defer sb.mux.Unlock()
 
+	sb.addSession(s)
+	return sb.save()
+}
+
+func (sb *sessionBuff) addSession(s *Session) {
+
 	sb.sessions = append([]*Session{s}, sb.sessions...)
 	sb.sessionByID[s.GetID()] = s
 	return
 }
 
-func (sb *SessionBuff) GetNewest() *Session {
+func (sb *sessionBuff) GetNewest() *Session {
 	sb.mux.RLock()
 	defer sb.mux.RUnlock()
 	if len(sb.sessions) == 0 {
@@ -41,7 +143,7 @@ func (sb *SessionBuff) GetNewest() *Session {
 }
 
 // returns the session which is most likely to be successful for sending
-func (sb *SessionBuff) GetSessionForSending() *Session {
+func (sb *sessionBuff) GetSessionForSending() *Session {
 	sb.mux.RLock()
 	defer sb.mux.RUnlock()
 	if len(sb.sessions) == 0 {
@@ -79,7 +181,7 @@ func (sb *SessionBuff) GetSessionForSending() *Session {
 	return nil
 }
 
-func (sb *SessionBuff) GetNewestConfirmed() *Session {
+func (sb *sessionBuff) GetNewestConfirmed() *Session {
 	sb.mux.RLock()
 	defer sb.mux.RUnlock()
 	if len(sb.sessions) == 0 {
@@ -97,7 +199,7 @@ func (sb *SessionBuff) GetNewestConfirmed() *Session {
 	return nil
 }
 
-func (sb *SessionBuff) GetByID(id SessionID) *Session {
+func (sb *sessionBuff) GetByID(id SessionID) *Session {
 	sb.mux.RLock()
 	defer sb.mux.RUnlock()
 	return sb.sessionByID[id]
@@ -106,7 +208,7 @@ func (sb *SessionBuff) GetByID(id SessionID) *Session {
 // 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
-func (sb *SessionBuff) Confirm(id SessionID) error {
+func (sb *sessionBuff) Confirm(id SessionID) error {
 	sb.mux.Lock()
 	defer sb.mux.Unlock()
 	s, ok := sb.sessionByID[id]
@@ -114,16 +216,44 @@ func (sb *SessionBuff) Confirm(id SessionID) error {
 		return errors.Errorf("Could not confirm session %s, does not exist", s.GetID())
 	}
 
-	s.confirm()
-	return nil
-}
+	err := s.confirm()
+	if err != nil {
+		jww.FATAL.Panicf("Failed to confirm session "+
+			"%s for %s: %s", s.GetID(), sb.manager.partner, err.Error())
+	}
 
-func (sb *SessionBuff) Clean() error {
-}
+	return sb.clean()
 }
-//find the sessions position in the session buffer
-loc := -1
-for i, sBuf := range sb.sessions{
-if sBuf==s{
-loc = i
+
+func (sb *sessionBuff) clean() error {
+
+	numConfirmed := uint(0)
+
+	var newSessions []*Session
+
+	for _, s := range sb.sessions {
+		if s.IsConfirmed() {
+			numConfirmed++
+			//if the number of newer confirmed is sufficient, delete the confirmed
+			if numConfirmed > maxUnconfirmed {
+				delete(sb.sessionByID, s.GetID())
+				err := s.Delete()
+				if err != nil {
+					jww.FATAL.Panicf("Failed to delete session store "+
+						"%s for %s: %s", s.GetID(), sb.manager.partner, err.Error())
+				}
+
+				break
+			}
+		}
+		newSessions = append(newSessions, s)
+	}
+
+	sb.sessions = newSessions
+
+	return sb.save()
 }
+
+func makeSessionBuffKey(keyPrefix string, partnerID *id.ID) string {
+	return keyPrefix + "sessionBuffer" + base64.StdEncoding.EncodeToString(partnerID.Marshal())
+}
\ No newline at end of file
diff --git a/key/sessionID.go b/key/sessionID.go
new file mode 100644
index 0000000000000000000000000000000000000000..4ac8edfb78bfd1a80247571a8a7d76c9a49f9176
--- /dev/null
+++ b/key/sessionID.go
@@ -0,0 +1,18 @@
+package key
+
+import "encoding/base64"
+
+type SessionID [32]byte
+
+func (sid SessionID) Bytes() []byte {
+	return sid[:]
+}
+
+func (sid SessionID) String() string {
+	return base64.StdEncoding.EncodeToString(sid[:])
+}
+
+//builds the
+func makeSessionKey(sid SessionID) string {
+	return sid.String()
+}
diff --git a/key/sessionType.go b/key/sessionType.go
new file mode 100644
index 0000000000000000000000000000000000000000..163509b30297e80e558bf1c6b229581558d99ed0
--- /dev/null
+++ b/key/sessionType.go
@@ -0,0 +1,19 @@
+package key
+
+type SessionType uint8
+
+const (
+	Send SessionType = iota
+	Receive
+)
+
+func (st SessionType) String() string {
+	switch st {
+	case Send:
+		return "Send"
+	case Receive:
+		return "Receive"
+	default:
+		return "Unknown"
+	}
+}
diff --git a/key/sessionType_test.go b/key/sessionType_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..109376ac2983b1dd6886b52e4273ce40977bb5eb
--- /dev/null
+++ b/key/sessionType_test.go
@@ -0,0 +1,28 @@
+package key
+
+import (
+	"math"
+	"testing"
+)
+
+//tests the stringers for all possible sessions types are correct
+func TestSessionType_String(t *testing.T) {
+	for i := 0; i <= math.MaxUint8; i++ {
+		st := SessionType(i)
+		if st.String() != correctString(i) {
+			t.Errorf("Session Name for %v incorrect. Expected: %s, "+
+				"Received: %s", i, correctString(i), st.String())
+		}
+	}
+}
+
+func correctString(i int) string {
+	switch i {
+	case 0:
+		return "Send"
+	case 1:
+		return "Receive"
+	default:
+		return "Unknown"
+	}
+}
diff --git a/key/stateVector.go b/key/stateVector.go
new file mode 100644
index 0000000000000000000000000000000000000000..2dbe610794989f18968a7b4acdb967985a771477
--- /dev/null
+++ b/key/stateVector.go
@@ -0,0 +1,188 @@
+package key
+
+import (
+	"encoding/json"
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage"
+	"sync"
+	"time"
+)
+
+type stateVector struct {
+	ctx *context
+	key string
+
+	vect []uint64
+
+	firstAvailable uint32
+	numkeys        uint32
+	numAvalible    uint32
+
+	mux sync.RWMutex
+}
+
+type stateVectorDisk struct {
+	vect           []uint64
+	firstAvailable uint32
+	numkeys        uint32
+}
+
+func newStateVector(ctx *context, key string, numkeys uint32) *stateVector {
+	numBlocks := (numkeys + 63) / 64
+
+	sv := &stateVector{
+		ctx:            ctx,
+		vect:           make([]uint64, numBlocks),
+		key:            key,
+		firstAvailable: 0,
+		numAvalible:    numkeys,
+		numkeys:        numkeys,
+	}
+
+	return sv
+}
+
+func loadStateVector(ctx *context, key string) (*stateVector, error) {
+	sv := &stateVector{
+		ctx: ctx,
+		key: key,
+	}
+
+	obj, err := ctx.kv.Get(key)
+	if err != nil {
+		return nil, err
+	}
+
+	err = sv.unmarshal(obj.Data)
+	if err != nil {
+		return nil, err
+	}
+
+	return sv, nil
+}
+
+func (sv *stateVector) save() error {
+	now, err := time.Now().MarshalText()
+	if err != nil {
+		return err
+	}
+
+	data, err := sv.marshal()
+	if err != nil {
+		return err
+	}
+
+	obj := storage.VersionedObject{
+		Version:   currentSessionVersion,
+		Timestamp: now,
+		Data:      data,
+	}
+
+	return sv.ctx.kv.Set(sv.key, &obj)
+}
+
+func (sv *stateVector) Use(keynum uint32) error {
+	sv.mux.Lock()
+	defer sv.mux.Unlock()
+
+	block := keynum / 64
+	pos := keynum % 64
+
+	sv.vect[block] |= 1 << pos
+
+	if keynum == sv.firstAvailable {
+		sv.nextAvailable()
+	}
+
+	sv.numAvalible--
+
+	return sv.save()
+}
+
+func (sv *stateVector) GetNumAvailable() uint32 {
+	sv.mux.RLock()
+	defer sv.mux.RUnlock()
+	return sv.numAvalible
+}
+
+func (sv *stateVector) Used(keynum uint32) bool {
+	sv.mux.RLock()
+	defer sv.mux.RUnlock()
+
+	block := keynum / 64
+	pos := keynum % 64
+
+	sv.vect[block] |= 1 << pos
+
+	return (sv.vect[block]>>pos)&1 == 1
+}
+
+func (sv *stateVector) Next() (uint32, error) {
+	sv.mux.Lock()
+	defer sv.mux.Lock()
+
+	if sv.firstAvailable >= sv.numkeys {
+		return sv.numkeys, errors.New("No keys remaining")
+	}
+
+	next := sv.firstAvailable
+
+	sv.nextAvailable()
+	sv.numAvalible--
+
+	return next, sv.save()
+
+}
+
+func (sv *stateVector) GetNumKeys() uint32 {
+	return sv.numkeys
+}
+
+// finds the next used state and sets that as firstAvailable. This does not
+// execute a store and a store must be executed after.
+func (sv *stateVector) nextAvailable() {
+
+	block := (sv.firstAvailable + 1) / 64
+	pos := (sv.firstAvailable + 1) % 64
+
+	for ; block < uint32(len(sv.vect)) && sv.vect[block]>>pos&1 == 1; pos++ {
+		if pos == 64 {
+			pos = 0
+			block++
+		}
+	}
+
+	sv.firstAvailable = pos
+}
+
+//ekv functions
+func (sv *stateVector) marshal() ([]byte, error) {
+	svd := stateVectorDisk{}
+
+	svd.firstAvailable = sv.firstAvailable
+	svd.numkeys = sv.numkeys
+	svd.vect = sv.vect
+
+	return json.Marshal(&svd)
+}
+
+func (sv *stateVector) unmarshal(b []byte) error {
+
+	svd := stateVectorDisk{}
+
+	err := json.Unmarshal(b, &svd)
+
+	if err != nil {
+		return err
+	}
+
+	sv.firstAvailable = svd.firstAvailable
+	sv.numkeys = svd.numkeys
+	sv.vect = svd.vect
+
+	return nil
+}
+
+func makeStateVectorKey(prefix string, sid SessionID) string {
+	return sid.String() + prefix
+}
diff --git a/key/store.go b/key/store.go
index 4aeb5ef450d1e0cd2d30a376ae9a9257aab7df46..fdef832dbfbfb76d372700bfb3c86e5b00a36000 100644
--- a/key/store.go
+++ b/key/store.go
@@ -1,22 +1,195 @@
 package key
 
 import (
+	"encoding/json"
+	"github.com/pkg/errors"
+	"gitlab.com/elixxir/client/storage"
+	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
+	"sync"
+	jww "github.com/spf13/jwalterweatherman"
+	"time"
 )
 
+const storeKey = "keyStore"
+const currentStoreVersion = 0
+
 type Store struct {
-	managers         map[id.ID]*Manager
-	fingerprintToKey map[format.Fingerprint]*Key
+	managers map[id.ID]*Manager
+	mux      sync.RWMutex
+
+	fingerprints
+
+	context
+}
+
+func NewStore(grp *cyclic.Group, kv *storage.Session) *Store {
+	fingerprints := newFingerprints()
+	return &Store{
+		managers:     make(map[id.ID]*Manager),
+		fingerprints: fingerprints,
+		context: context{
+			fa:  &fingerprints,
+			grp: grp,
+			kv:  kv,
+		},
+	}
+
+}
+
+func LoadStore(grp *cyclic.Group, kv *storage.Session) (*Store, error) {
+	s := NewStore(grp, kv)
+
+	obj, err := kv.Get(storeKey)
+	if err != nil {
+		return nil, err
+	}
+
+	err = s.unmarshal(obj.Data)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return s, nil
+}
+
+func (s *Store) save() error {
+	now, err := time.Now().MarshalText()
+	if err != nil {
+		return err
+	}
+
+	data, err := s.marshal()
+	if err != nil {
+		return err
+	}
+
+	obj := storage.VersionedObject{
+		Version:   currentStoreVersion,
+		Timestamp: now,
+		Data:      data,
+	}
+
+	return s.kv.Set(storeKey, &obj)
+}
+
+func (s *Store) AddPartner(partnerID *id.ID, myPrivKey *cyclic.Int,
+	partnerPubKey *cyclic.Int, sendParams, receiveParams SessionParams) error {
+	s.mux.Lock()
+	defer s.mux.Unlock()
+
+	m, err := newManager(&s.context, partnerID, myPrivKey, partnerPubKey, sendParams, receiveParams)
+
+	if err != nil {
+		return err
+	}
+
+	s.managers[*partnerID] = m
+
+	return s.save()
+}
+
+func (s *Store) GetPartner(partnerID *id.ID) (*Manager, error) {
+	s.mux.RLock()
+	defer s.mux.RUnlock()
+
+	m, ok := s.managers[*partnerID]
+
+	if !ok {
+		return nil, errors.New("Cound not find manager for partner")
+	}
+
+	return m, nil
+}
+
+//ekv functions
+func (s *Store) marshal() ([]byte, error) {
+
+	contacts := make([]id.ID, len(s.managers))
+
+	index := 0
+	for partnerID := range s.managers {
+		contacts[index] = partnerID
+	}
+
+	return json.Marshal(&contacts)
+}
+
+func (s *Store) unmarshal(b []byte) error {
+
+	var contacts []id.ID
+
+	err := json.Unmarshal(b, &contacts)
+
+	if err != nil {
+		return err
+	}
+
+	for _, partnerID := range contacts {
+		// load the manager. Manager handles adding the fingerprints via the
+		// context object
+		manager, err := loadManager(&s.context, &partnerID)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to load manager for partner %s: %s", &partnerID, err.Error())
+		}
+
+		s.managers[partnerID] = manager
+	}
+	return nil
 }
 
-type StoreDisk struct {
-	contacts []id.ID
+type fingerprints struct {
+	toKey map[format.Fingerprint]*Key
+	mux   sync.RWMutex
 }
 
-func (s *Store) CleanManager(partner id.ID) error {
-	//lookup
+func newFingerprints() fingerprints {
+	return fingerprints{
+		toKey: make(map[format.Fingerprint]*Key),
+	}
+}
 
-	//get sessions to be removed
+//fingerprint adhere to the fingerprintAccess interface
+func (f *fingerprints) add(keys []*Key) {
+	f.mux.Lock()
+	defer f.mux.Unlock()
 
+	for _, k := range keys {
+		f.toKey[k.Fingerprint()] = k
+	}
 }
+
+func (f *fingerprints) remove(keys []*Key) {
+	f.mux.Lock()
+	defer f.mux.Unlock()
+
+	for _, k := range keys {
+		delete(f.toKey, k.Fingerprint())
+	}
+}
+
+func (f *fingerprints) Pop(fingerprint format.Fingerprint) (*Key, error) {
+	f.mux.Lock()
+	defer f.mux.Unlock()
+
+	key, ok := f.toKey[fingerprint]
+
+	if !ok {
+		return nil, errors.New("Key could not be found")
+	}
+
+	delete(f.toKey, fingerprint)
+
+	err := key.denoteUse()
+
+	if err != nil {
+		return nil, err
+	}
+
+	key.fp = &fingerprint
+
+	return key, nil
+}
+
diff --git a/storage/session.go b/storage/session.go
index 95777d7c26cc2e896a7403fe45c91ce5e1dfbcfc..b521cdf85c6754509d480bfae69d0c8375dbbbfd 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -50,6 +50,11 @@ func (s *Session) Set(key string, object *VersionedObject) error {
 	return s.kv.Set(key, object)
 }
 
+// Deletes a value in the session
+func (s *Session) Delete(key string) error {
+	return s.kv.Delete(key)
+}
+
 // Obtain the LastMessageID from the Session
 func (s *Session) GetLastMessageId() (string, error) {
 	v, err := s.Get("LastMessageID")