diff --git a/storage/user/cryptographic.go b/storage/user/cryptographic.go index fe5d9b59ab979d6e5df20117ebdb43a129f6df31..9a78f4ef638502228fc299a06ba9f0d5ff211230 100644 --- a/storage/user/cryptographic.go +++ b/storage/user/cryptographic.go @@ -21,6 +21,13 @@ type CryptographicIdentity struct { isPrecanned bool } +type ciDisk struct { + UserID *id.ID + Salt []byte + RsaKey *rsa.PrivateKey + IsPrecanned bool +} + func newCryptographicIdentity(uid *id.ID, salt []byte, rsaKey *rsa.PrivateKey, isPrecanned bool, kv *versioned.KV) *CryptographicIdentity { @@ -47,18 +54,35 @@ func loadCryptographicIdentity(kv *versioned.KV) (*CryptographicIdentity, error) } var resultBuffer bytes.Buffer - var result *CryptographicIdentity + result := &CryptographicIdentity{} + decodable := &ciDisk{} + resultBuffer.Write(obj.Data) dec := gob.NewDecoder(&resultBuffer) - err = dec.Decode(result) + err = dec.Decode(decodable) + + if decodable != nil { + result.isPrecanned = decodable.IsPrecanned + result.rsaKey = decodable.RsaKey + result.salt = decodable.Salt + result.userID = decodable.UserID + } return result, err } func (ci *CryptographicIdentity) save(kv *versioned.KV) error { var userDataBuffer bytes.Buffer + + encodable := &ciDisk{ + UserID: ci.userID, + Salt: ci.salt, + RsaKey: ci.rsaKey, + IsPrecanned: ci.isPrecanned, + } + enc := gob.NewEncoder(&userDataBuffer) - err := enc.Encode(ci) + err := enc.Encode(encodable) if err != nil { return err } diff --git a/storage/user/cryptographic_test.go b/storage/user/cryptographic_test.go new file mode 100644 index 0000000000000000000000000000000000000000..71c2dff95230612ee249c5363c274c52b8c2c3b6 --- /dev/null +++ b/storage/user/cryptographic_test.go @@ -0,0 +1,88 @@ +package user + +import ( + "bytes" + "crypto/rand" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/primitives/id" + "testing" +) + +// Test for NewCryptographicIdentity function +func TestNewCryptographicIdentity(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("zezima", id.User, t) + _ = newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) + + _, err := kv.Get(cryptographicIdentityKey) + if err != nil { + t.Errorf("Did not store cryptographic identity") + } +} + +// Test loading cryptographic identity from KV store +func TestLoadCryptographicIdentity(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("zezima", id.User, t) + ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) + + err := ci.save(kv) + if err != nil { + t.Errorf("Did not store cryptographic identity: %+v", err) + } + + newCi, err := loadCryptographicIdentity(kv) + if err != nil { + t.Errorf("Failed to load cryptographic identity: %+v", err) + } + if !ci.userID.Cmp(newCi.userID) { + t.Errorf("Did not load expected ci. Expected: %+v, Received: %+v", ci.userID, newCi.userID) + } +} + +// Happy path for GetRSA function +func TestCryptographicIdentity_GetRSA(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("zezima", id.User, t) + pk, err := rsa.GenerateKey(rand.Reader, 64) + if err != nil { + t.Errorf("Failed to generate pk") + } + ci := newCryptographicIdentity(uid, []byte("salt"), pk, false, kv) + if ci.GetRSA().D != pk.D { + t.Errorf("Did not receive expected RSA key. Expected: %+v, Received: %+v", pk, ci.GetRSA()) + } +} + +// Happy path for GetSalt function +func TestCryptographicIdentity_GetSalt(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("zezima", id.User, t) + salt := []byte("NaCl") + ci := newCryptographicIdentity(uid, salt, &rsa.PrivateKey{}, false, kv) + if bytes.Compare(ci.GetSalt(), salt) != 0 { + t.Errorf("Did not get expected salt. Expected: %+v, Received: %+v", salt, ci.GetSalt()) + } +} + +// Happy path for GetUserID function +func TestCryptographicIdentity_GetUserID(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("zezima", id.User, t) + ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) + if !ci.GetUserID().Cmp(uid) { + t.Errorf("Did not receive expected user ID. Expected: %+v, Received: %+v", uid, ci.GetUserID()) + } +} + +// Happy path for IsPrecanned functions +func TestCryptographicIdentity_IsPrecanned(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("zezima", id.User, t) + ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, true, kv) + if !ci.IsPrecanned() { + t.Error("I really don't know how this could happen") + } +} diff --git a/storage/user/regValidationSig_test.go b/storage/user/regValidationSig_test.go new file mode 100644 index 0000000000000000000000000000000000000000..d2c3f758ec4de5cbb01b30faae38a32231674c97 --- /dev/null +++ b/storage/user/regValidationSig_test.go @@ -0,0 +1,84 @@ +package user + +import ( + "bytes" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/primitives/id" + "testing" + "time" +) + +// Test User GetRegistrationValidationSignature function +func TestUser_GetRegistrationValidationSignature(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } + + sig := []byte("testsignature") + u.SetRegistrationValidationSignature(sig) + if bytes.Compare(sig, u.regValidationSig) != 0 { + t.Errorf("Failed to set user object signature field. Expected: %+v, Received: %+v", + sig, u.regValidationSig) + } + + if bytes.Compare(u.GetRegistrationValidationSignature(), sig) != 0 { + t.Errorf("Did not receive expected result from GetRegistrationValidationSignature. "+ + "Expected: %+v, Received: %+v", sig, u.GetRegistrationValidationSignature()) + } +} + +// Test SetRegistrationValidationSignature setter +func TestUser_SetRegistrationValidationSignature(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } + + sig := []byte("testsignature") + u.SetRegistrationValidationSignature(sig) + if bytes.Compare(sig, u.regValidationSig) != 0 { + t.Errorf("Failed to set user object signature field. Expected: %+v, Received: %+v", + sig, u.regValidationSig) + } + + obj, err := u.kv.Get(regValidationSigKey) + if err != nil { + t.Errorf("Failed to get reg vaildation signature key: %+v", err) + } + if bytes.Compare(obj.Data, sig) != 0 { + t.Errorf("Did not properly set reg validation signature key in kv store.\nExpected: %+v, Received: %+v", + sig, obj.Data) + } +} + +// Test loading registrationValidationSignature from the KV store +func TestUser_loadRegistrationValidationSignature(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } + + sig := []byte("signature") + err = kv.Set(regValidationSigKey, &versioned.Object{ + Version: currentRegValidationSigVersion, + Timestamp: time.Now(), + Data: sig, + }) + if err != nil { + t.Errorf("Failed to set reg validation sig key in kv store: %+v", err) + } + + u.loadRegistrationValidationSignature() + if bytes.Compare(u.regValidationSig, sig) != 0 { + t.Errorf("Expected sig did not match loaded. Expected: %+v, Received: %+v", sig, u.regValidationSig) + } +} diff --git a/storage/user/user_test.go b/storage/user/user_test.go new file mode 100644 index 0000000000000000000000000000000000000000..eab18d6f49720299af764d6e4e39a85d3a9fad8f --- /dev/null +++ b/storage/user/user_test.go @@ -0,0 +1,57 @@ +package user + +import ( + "bytes" + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/primitives/id" + "testing" +) + +// Test loading user from a KV store +func TestLoadUser(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + _, err := LoadUser(kv) + + if err == nil { + t.Errorf("Should have failed to load identity from empty kv") + } + + uid := id.NewIdFromString("test", id.User, t) + ci := newCryptographicIdentity(uid, []byte("salt"), &rsa.PrivateKey{}, false, kv) + err = ci.save(kv) + if err != nil { + t.Errorf("Failed to save ci to kv: %+v", err) + } + + _, err = LoadUser(kv) + if err != nil { + t.Errorf("Failed to load user: %+v", err) + } +} + +// Test NewUser function +func TestNewUser(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } +} + +// Test GetCryptographicIdentity function from user +func TestUser_GetCryptographicIdentity(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } + + ci := u.GetCryptographicIdentity() + if bytes.Compare(ci.salt, []byte("salt")) != 0 { + t.Errorf("Cryptographic Identity not retrieved properly") + } +} diff --git a/storage/user/username_test.go b/storage/user/username_test.go new file mode 100644 index 0000000000000000000000000000000000000000..21a720593fcfb458fc8d1d913d5152b30d80db50 --- /dev/null +++ b/storage/user/username_test.go @@ -0,0 +1,88 @@ +package user + +import ( + "gitlab.com/elixxir/client/storage/versioned" + "gitlab.com/elixxir/ekv" + "gitlab.com/xx_network/crypto/signature/rsa" + "gitlab.com/xx_network/primitives/id" + "testing" + "time" +) + +// Test normal function and errors for User's SetUsername function +func TestUser_SetUsername(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } + + u1 := "zezima" + u2 := "dunkey" + err = u.SetUsername(u1) + if err != nil { + t.Errorf("Failed to set username: %+v", err) + } + + err = u.SetUsername(u2) + if err == nil { + t.Error("Did not error when attempting to set a new username") + } + + o, err := u.kv.Get(usernameKey) + if err != nil { + t.Errorf("Didn't get username from user kv store: %+v", err) + } + + if string(o.Data) != u1 { + t.Errorf("Expected username was not stored.\nExpected: %s\tReceived: %s", u1, string(o.Data)) + } +} + +// Test functionality of User's GetUsername function +func TestUser_GetUsername(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } + + _, err = u.GetUsername() + if err == nil { + t.Error("GetUsername should return an error if username is not set") + } + + u1 := "zezima" + u.username = u1 + username, err := u.GetUsername() + if err != nil { + t.Errorf("Failed to get username when set: %+v", err) + } + if username != u1 { + t.Errorf("Somehow got the wrong username") + } +} + +// Test the loadUsername helper function +func TestUser_loadUsername(t *testing.T) { + kv := versioned.NewKV(make(ekv.Memstore)) + uid := id.NewIdFromString("test", id.User, t) + u, err := NewUser(kv, uid, []byte("salt"), &rsa.PrivateKey{}, false) + if err != nil || u == nil { + t.Errorf("Failed to create new user: %+v", err) + } + + u1 := "zezima" + + err = u.kv.Set(usernameKey, &versioned.Object{ + Version: currentUsernameVersion, + Timestamp: time.Now(), + Data: []byte(u1), + }) + u.loadUsername() + if u.username != u1 { + t.Errorf("Username was not properly loaded from kv.\nExpected: %s, Received: %s", u1, u.username) + } +}