Skip to content
Snippets Groups Projects
Commit 5a6c0b04 authored by Jake Taylor's avatar Jake Taylor
Browse files

added new version of CryptographicIdentity storage to support storing...

added new version of CryptographicIdentity storage to support storing e2eDhKeys and loading legacy e2eDhKeys
parent f403d392
No related branches found
No related tags found
3 merge requests!510Release,!267Make BuildReceptionIdentity public, and make backup restore function return a...,!263Hotfix/refactor cmd
...@@ -10,15 +10,19 @@ package user ...@@ -10,15 +10,19 @@ package user
import ( import (
"bytes" "bytes"
"encoding/gob" "encoding/gob"
"encoding/json"
"github.com/pkg/errors" "github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/storage/utility"
"gitlab.com/elixxir/client/storage/versioned" "gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/netTime" "gitlab.com/xx_network/primitives/netTime"
) )
const currentCryptographicIdentityVersion = 0 const originalCryptographicIdentityVersion = 0
const currentCryptographicIdentityVersion = 1
const cryptographicIdentityKey = "cryptographicIdentity" const cryptographicIdentityKey = "cryptographicIdentity"
type CryptographicIdentity struct { type CryptographicIdentity struct {
...@@ -29,6 +33,8 @@ type CryptographicIdentity struct { ...@@ -29,6 +33,8 @@ type CryptographicIdentity struct {
receptionSalt []byte receptionSalt []byte
receptionRsaKey *rsa.PrivateKey receptionRsaKey *rsa.PrivateKey
isPrecanned bool isPrecanned bool
e2eDhPrivateKey *cyclic.Int
e2eDhPublicKey *cyclic.Int
} }
type ciDisk struct { type ciDisk struct {
...@@ -41,10 +47,23 @@ type ciDisk struct { ...@@ -41,10 +47,23 @@ type ciDisk struct {
IsPrecanned bool IsPrecanned bool
} }
type ciDiskV1 struct {
TransmissionID *id.ID
TransmissionSalt []byte
TransmissionRsaKey *rsa.PrivateKey
ReceptionID *id.ID
ReceptionSalt []byte
ReceptionRsaKey *rsa.PrivateKey
IsPrecanned bool
E2eDhPrivateKey []byte
E2eDhPublicKey []byte
}
func newCryptographicIdentity(transmissionID, receptionID *id.ID, func newCryptographicIdentity(transmissionID, receptionID *id.ID,
transmissionSalt, receptionSalt []byte, transmissionSalt, receptionSalt []byte,
transmissionRsa, receptionRsa *rsa.PrivateKey, transmissionRsa, receptionRsa *rsa.PrivateKey,
isPrecanned bool, kv *versioned.KV) *CryptographicIdentity { isPrecanned bool, e2eDhPrivateKey, e2eDhPublicKey *cyclic.Int,
kv *versioned.KV) *CryptographicIdentity {
ci := &CryptographicIdentity{ ci := &CryptographicIdentity{
transmissionID: transmissionID, transmissionID: transmissionID,
...@@ -54,6 +73,8 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID, ...@@ -54,6 +73,8 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID,
receptionSalt: receptionSalt, receptionSalt: receptionSalt,
receptionRsaKey: receptionRsa, receptionRsaKey: receptionRsa,
isPrecanned: isPrecanned, isPrecanned: isPrecanned,
e2eDhPrivateKey: e2eDhPrivateKey,
e2eDhPublicKey: e2eDhPublicKey,
} }
if err := ci.save(kv); err != nil { if err := ci.save(kv); err != nil {
...@@ -64,23 +85,55 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID, ...@@ -64,23 +85,55 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID,
return ci return ci
} }
func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) { // loadOriginalCryptographicIdentity attempts to load the originalCryptographicIdentityVersion CryptographicIdentity
obj, err := kv.Get(cryptographicIdentityKey, func loadOriginalCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) {
currentCryptographicIdentityVersion) result := &CryptographicIdentity{}
obj, err := kv.Get(cryptographicIdentityKey, originalCryptographicIdentityVersion)
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "Failed to get user "+ return nil, errors.WithMessagef(err, "Failed to get version %d user "+
"cryptographic identity from EKV") "cryptographic identity from EKV", originalCryptographicIdentityVersion)
} }
var resultBuffer bytes.Buffer var resultBuffer bytes.Buffer
result := &CryptographicIdentity{}
decodable := &ciDisk{} decodable := &ciDisk{}
resultBuffer.Write(obj.Data) resultBuffer.Write(obj.Data)
dec := gob.NewDecoder(&resultBuffer) dec := gob.NewDecoder(&resultBuffer)
err = dec.Decode(decodable) err = dec.Decode(decodable)
if err != nil {
return nil, err
}
result.isPrecanned = decodable.IsPrecanned
result.receptionRsaKey = decodable.ReceptionRsaKey
result.transmissionRsaKey = decodable.TransmissionRsaKey
result.transmissionSalt = decodable.TransmissionSalt
result.transmissionID = decodable.TransmissionID
result.receptionID = decodable.ReceptionID
result.receptionSalt = decodable.ReceptionSalt
return result, nil
}
func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) {
result := &CryptographicIdentity{}
obj, err := kv.Get(cryptographicIdentityKey,
currentCryptographicIdentityVersion)
if err != nil {
result, err = loadOriginalCryptographicIdentity(kv)
if err != nil {
return nil, err
}
// Populate E2E keys from legacy storage
result.e2eDhPublicKey, result.e2eDhPrivateKey = loadLegacyDHKeys(kv)
// Migrate to the new version in storage
return result, result.save(kv)
}
decodable := &ciDiskV1{}
err = json.Unmarshal(obj.Data, decodable)
if err != nil {
return nil, err
}
if decodable != nil {
result.isPrecanned = decodable.IsPrecanned result.isPrecanned = decodable.IsPrecanned
result.receptionRsaKey = decodable.ReceptionRsaKey result.receptionRsaKey = decodable.ReceptionRsaKey
result.transmissionRsaKey = decodable.TransmissionRsaKey result.transmissionRsaKey = decodable.TransmissionRsaKey
...@@ -88,15 +141,58 @@ func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) ...@@ -88,15 +141,58 @@ func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error)
result.transmissionID = decodable.TransmissionID result.transmissionID = decodable.TransmissionID
result.receptionID = decodable.ReceptionID result.receptionID = decodable.ReceptionID
result.receptionSalt = decodable.ReceptionSalt result.receptionSalt = decodable.ReceptionSalt
result.e2eDhPrivateKey = &cyclic.Int{}
err = result.e2eDhPrivateKey.UnmarshalJSON(decodable.E2eDhPrivateKey)
if err != nil {
return nil, err
}
result.e2eDhPublicKey = &cyclic.Int{}
err = result.e2eDhPublicKey.UnmarshalJSON(decodable.E2eDhPublicKey)
if err != nil {
return nil, err
}
return result, nil
} }
return result, err // loadLegacyDHKeys attempts to load DH Keys from legacy storage. It
// prints a warning to the log as users should be using ReceptionIdentity
// instead of PortableUserInfo
func loadLegacyDHKeys(kv *versioned.KV) (pub, priv *cyclic.Int) {
// Legacy package prefixes and keys, see e2e/ratchet/storage.go
packagePrefix := "e2eSession"
pubKeyKey := "DhPubKey"
privKeyKey := "DhPrivKey"
kvPrefix := kv.Prefix(packagePrefix)
privKey, err := utility.LoadCyclicKey(kvPrefix, privKeyKey)
if err != nil {
jww.ERROR.Printf("Failed to load e2e DH private key: %v", err)
return nil, nil
}
pubKey, err := utility.LoadCyclicKey(kvPrefix, pubKeyKey)
if err != nil {
jww.ERROR.Printf("Failed to load e2e DH public key: %v", err)
return nil, nil
}
return pubKey, privKey
} }
func (ci *CryptographicIdentity) save(kv *versioned.KV) error { func (ci *CryptographicIdentity) save(kv *versioned.KV) error {
var userDataBuffer bytes.Buffer dhPriv, err := ci.e2eDhPrivateKey.MarshalJSON()
if err != nil {
return err
}
dhPub, err := ci.e2eDhPublicKey.MarshalJSON()
if err != nil {
return err
}
encodable := &ciDisk{ encodable := &ciDiskV1{
TransmissionID: ci.transmissionID, TransmissionID: ci.transmissionID,
TransmissionSalt: ci.transmissionSalt, TransmissionSalt: ci.transmissionSalt,
TransmissionRsaKey: ci.transmissionRsaKey, TransmissionRsaKey: ci.transmissionRsaKey,
...@@ -104,10 +200,11 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { ...@@ -104,10 +200,11 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error {
ReceptionSalt: ci.receptionSalt, ReceptionSalt: ci.receptionSalt,
ReceptionRsaKey: ci.receptionRsaKey, ReceptionRsaKey: ci.receptionRsaKey,
IsPrecanned: ci.isPrecanned, IsPrecanned: ci.isPrecanned,
E2eDhPrivateKey: dhPriv,
E2eDhPublicKey: dhPub,
} }
enc := gob.NewEncoder(&userDataBuffer) enc, err := json.Marshal(&encodable)
err := enc.Encode(encodable)
if err != nil { if err != nil {
return err return err
} }
...@@ -115,7 +212,7 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error { ...@@ -115,7 +212,7 @@ func (ci *CryptographicIdentity) save(kv *versioned.KV) error {
obj := &versioned.Object{ obj := &versioned.Object{
Version: currentCryptographicIdentityVersion, Version: currentCryptographicIdentityVersion,
Timestamp: netTime.Now(), Timestamp: netTime.Now(),
Data: userDataBuffer.Bytes(), Data: enc,
} }
return kv.Set(cryptographicIdentityKey, return kv.Set(cryptographicIdentityKey,
...@@ -149,3 +246,11 @@ func (ci *CryptographicIdentity) GetTransmissionRSA() *rsa.PrivateKey { ...@@ -149,3 +246,11 @@ func (ci *CryptographicIdentity) GetTransmissionRSA() *rsa.PrivateKey {
func (ci *CryptographicIdentity) IsPrecanned() bool { func (ci *CryptographicIdentity) IsPrecanned() bool {
return ci.isPrecanned return ci.isPrecanned
} }
func (ci *CryptographicIdentity) GetE2eDhPublicKey() *cyclic.Int {
return ci.e2eDhPublicKey.DeepCopy()
}
func (ci *CryptographicIdentity) GetE2eDhPrivateKey() *cyclic.Int {
return ci.e2eDhPrivateKey.DeepCopy()
}
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
package user package user
import ( import (
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/storage/utility"
"gitlab.com/elixxir/crypto/backup" "gitlab.com/elixxir/crypto/backup"
"gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/crypto/signature/rsa"
...@@ -87,7 +85,6 @@ func NewUserFromBackup(backup *backup.Backup) Info { ...@@ -87,7 +85,6 @@ func NewUserFromBackup(backup *backup.Backup) Info {
func (u *User) PortableUserInfo() Info { func (u *User) PortableUserInfo() Info {
ci := u.CryptographicIdentity ci := u.CryptographicIdentity
pub, priv := u.loadLegacyDHKeys()
return Info{ return Info{
TransmissionID: ci.GetTransmissionID().DeepCopy(), TransmissionID: ci.GetTransmissionID().DeepCopy(),
TransmissionSalt: copySlice(ci.GetTransmissionSalt()), TransmissionSalt: copySlice(ci.GetTransmissionSalt()),
...@@ -97,40 +94,12 @@ func (u *User) PortableUserInfo() Info { ...@@ -97,40 +94,12 @@ func (u *User) PortableUserInfo() Info {
ReceptionSalt: copySlice(ci.GetReceptionSalt()), ReceptionSalt: copySlice(ci.GetReceptionSalt()),
ReceptionRSA: ci.GetReceptionRSA(), ReceptionRSA: ci.GetReceptionRSA(),
Precanned: ci.IsPrecanned(), Precanned: ci.IsPrecanned(),
E2eDhPrivateKey: priv, E2eDhPrivateKey: ci.GetE2eDhPrivateKey(),
E2eDhPublicKey: pub, E2eDhPublicKey: ci.GetE2eDhPublicKey(),
} }
} }
// loadLegacyDHKeys attempts to load DH Keys from legacy storage. It
// prints a warning to the log as users should be using ReceptionIdentity
// instead of PortableUserInfo
func (u *User) loadLegacyDHKeys() (pub, priv *cyclic.Int) {
jww.WARN.Printf("loading legacy e2e keys in cmix layer, please " +
"update your code to use xxdk.ReceptionIdentity")
// Legacy package prefixes and keys, see e2e/ratchet/storage.go
packagePrefix := "e2eSession"
pubKeyKey := "DhPubKey"
privKeyKey := "DhPrivKey"
kv := u.kv.Prefix(packagePrefix)
privKey, err := utility.LoadCyclicKey(kv, privKeyKey)
if err != nil {
jww.ERROR.Printf("Failed to load e2e DH private key: %v", err)
return nil, nil
}
pubKey, err := utility.LoadCyclicKey(kv, pubKeyKey)
if err != nil {
jww.ERROR.Printf("Failed to load e2e DH public key: %v", err)
return nil, nil
}
return pubKey, privKey
}
func copySlice(s []byte) []byte { func copySlice(s []byte) []byte {
n := make([]byte, len(s)) n := make([]byte, len(s))
copy(n, s) copy(n, s)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment