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
This commit is part of merge request !267. Comments created here will be created in the context of that merge request.
...@@ -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,39 +85,114 @@ func newCryptographicIdentity(transmissionID, receptionID *id.ID, ...@@ -64,39 +85,114 @@ 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
}
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 result.transmissionSalt = decodable.TransmissionSalt
result.transmissionSalt = decodable.TransmissionSalt result.transmissionID = decodable.TransmissionID
result.transmissionID = decodable.TransmissionID result.receptionID = decodable.ReceptionID
result.receptionID = decodable.ReceptionID result.receptionSalt = decodable.ReceptionSalt
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
} }
return result, 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
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
}
// 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.
Finish editing this message first!
Please register or to comment