Skip to content
Snippets Groups Projects
Commit 431bccbc authored by Josh Brooks's avatar Josh Brooks
Browse files

Merge branch 'api2.0' of git.xx.network:elixxir/client into josh/ParamsMarshaler

parents 3da31827 72a686b1
Branches
Tags
4 merge requests!510Release,!227Have all Params objects adhere to json.Marshaler/Unmarshaler,!226WIP: Api2.0,!207WIP: Client Restructure
Showing
with 295 additions and 535 deletions
This diff is collapsed.
......@@ -39,32 +39,6 @@ func createNewUser(rng *fastRNG.StreamGenerator) user.Info {
transmissionSalt, receptionSalt,
transmissionRsaKey, receptionRsaKey = createKeys(rng)
// Salt, UID, etc gen
stream := rng.GetStream()
transmissionSalt = make([]byte, SaltSize)
n, err := stream.Read(transmissionSalt)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
if n != SaltSize {
jww.FATAL.Panicf("transmissionSalt size too small: %d", n)
}
receptionSalt = make([]byte, SaltSize)
n, err = stream.Read(receptionSalt)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
if n != SaltSize {
jww.FATAL.Panicf("transmissionSalt size too small: %d", n)
}
stream.Close()
transmissionID, err := xx.NewID(transmissionRsaKey.GetPublic(),
transmissionSalt, id.User)
if err != nil {
......@@ -104,8 +78,11 @@ func createKeys(rng *fastRNG.StreamGenerator) (
stream := rng.GetStream()
transmissionRsaKey, err = rsa.GenerateKey(stream,
rsa.DefaultRSABitLen)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
transmissionSalt = make([]byte, 32)
_, err = stream.Read(receptionSalt)
_, err = stream.Read(transmissionSalt)
stream.Close()
if err != nil {
jww.FATAL.Panicf(err.Error())
......@@ -118,6 +95,9 @@ func createKeys(rng *fastRNG.StreamGenerator) (
stream := rng.GetStream()
receptionRsaKey, err = rsa.GenerateKey(stream,
rsa.DefaultRSABitLen)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
receptionSalt = make([]byte, 32)
_, err = stream.Read(receptionSalt)
stream.Close()
......@@ -127,6 +107,21 @@ func createKeys(rng *fastRNG.StreamGenerator) (
}()
wg.Wait()
isZero := func(data []byte) bool {
if len(data) == 0 {
return true
}
for i := len(data) - 1; i != 0; i-- {
if data[i] != 0 {
return false
}
}
return true
}
if isZero(receptionSalt) || isZero(transmissionSalt) {
jww.FATAL.Panicf("empty salt generation detected")
}
return
}
......
This diff is collapsed.
......@@ -120,7 +120,9 @@ func (s *state) confirm(partner contact.Contact, serviceTag string) (
s.event.Report(10, "Auth", "SendConfirmError", em)
}
if s.backupTrigger != nil {
s.backupTrigger("confirmed authenticated channel")
}
jww.INFO.Printf("Confirming Auth from %s to %s, msgDigest: %s",
partner.ID, s.e2e.GetReceptionID(),
......
......@@ -120,7 +120,7 @@ func (s *state) request(partner contact.Contact, myfacts fact.FactList,
jww.TRACE.Printf("AuthRequest PARTNERPUBKEY: %v",
partner.DhPubKey.TextVerbose(16, 0))
jww.TRACE.Printf("AuthRequest MYSIDHPUBKEY: %s",
sidhPub)
util.StringSIDHPubKey(sidhPub))
jww.TRACE.Printf("AuthRequest HistoricalPUBKEY: %v",
historicalDHPub.TextVerbose(16, 0))
......
......@@ -8,6 +8,11 @@
package auth
import (
"io"
"math/rand"
"testing"
"time"
"github.com/cloudflare/circl/dh/sidh"
"gitlab.com/elixxir/client/auth/store"
"gitlab.com/elixxir/client/cmix"
......@@ -29,10 +34,6 @@ import (
"gitlab.com/xx_network/crypto/large"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/id/ephemeral"
"io"
"math/rand"
"testing"
"time"
)
type mockEventManager struct{}
......@@ -185,7 +186,7 @@ loop:
}
func makeTestStore(t *testing.T) (*store.Store, *versioned.KV, []*cyclic.Int) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(0))
privKeys := make([]*cyclic.Int, 10)
for i := range privKeys {
......
......@@ -8,6 +8,10 @@
package store
import (
"math/rand"
"reflect"
"testing"
"github.com/cloudflare/circl/dh/sidh"
"gitlab.com/elixxir/client/storage/utility"
"gitlab.com/elixxir/client/storage/versioned"
......@@ -18,16 +22,13 @@ import (
"gitlab.com/elixxir/primitives/format"
"gitlab.com/xx_network/crypto/large"
"gitlab.com/xx_network/primitives/id"
"math/rand"
"reflect"
"testing"
)
// Tests that a confirmation for different partners and sentByFingerprints can be
// saved and loaded from storage via Store.StoreConfirmation and
// Store.LoadConfirmation.
func TestStore_StoreConfirmation_LoadConfirmation(t *testing.T) {
s := &Store{kv: versioned.NewKV(make(ekv.Memstore))}
s := &Store{kv: versioned.NewKV(ekv.MakeMemstore())}
prng := rand.New(rand.NewSource(42))
grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
......@@ -98,7 +99,7 @@ func TestStore_StoreConfirmation_LoadConfirmation(t *testing.T) {
// Tests that Store.DeleteConfirmation deletes the correct confirmation from
// storage and that it cannot be loaded from storage.
func TestStore_deleteConfirmation(t *testing.T) {
s := &Store{kv: versioned.NewKV(make(ekv.Memstore))}
s := &Store{kv: versioned.NewKV(ekv.MakeMemstore())}
prng := rand.New(rand.NewSource(42))
grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
......
......@@ -8,6 +8,10 @@
package store
import (
"math/rand"
"reflect"
"testing"
"github.com/cloudflare/circl/dh/sidh"
"gitlab.com/elixxir/client/storage/utility"
"gitlab.com/elixxir/client/storage/versioned"
......@@ -19,9 +23,6 @@ import (
"gitlab.com/xx_network/crypto/csprng"
"gitlab.com/xx_network/crypto/large"
"gitlab.com/xx_network/primitives/id"
"math/rand"
"reflect"
"testing"
)
// Tests the four possible cases of Store.CheckIfNegotationIsNew:
......@@ -36,7 +37,7 @@ import (
// Return newFingerprint = false, latest = true.
func TestStore_AddIfNew(t *testing.T) {
s := &Store{
kv: versioned.NewKV(make(ekv.Memstore)),
kv: versioned.NewKV(ekv.MakeMemstore()),
previousNegotiations: make(map[id.ID]bool),
}
prng := rand.New(rand.NewSource(42))
......@@ -161,7 +162,7 @@ func TestStore_AddIfNew(t *testing.T) {
// previousNegotiations in storage and any confirmations in storage.
func TestStore_deletePreviousNegotiationPartner(t *testing.T) {
s := &Store{
kv: versioned.NewKV(make(ekv.Memstore)),
kv: versioned.NewKV(ekv.MakeMemstore()),
previousNegotiations: make(map[id.ID]bool),
}
prng := rand.New(rand.NewSource(42))
......@@ -257,7 +258,7 @@ func TestStore_deletePreviousNegotiationPartner(t *testing.T) {
// via Store.savePreviousNegotiations andStore.newOrLoadPreviousNegotiations.
func TestStore_savePreviousNegotiations_newOrLoadPreviousNegotiations(t *testing.T) {
s := &Store{
kv: versioned.NewKV(make(ekv.Memstore)),
kv: versioned.NewKV(ekv.MakeMemstore()),
previousNegotiations: make(map[id.ID]bool),
}
prng := rand.New(rand.NewSource(42))
......@@ -291,7 +292,7 @@ func TestStore_savePreviousNegotiations_newOrLoadPreviousNegotiations(t *testing
// they do not exist.
func TestStore_newOrLoadPreviousNegotiations_noNegotiations(t *testing.T) {
s := &Store{
kv: versioned.NewKV(make(ekv.Memstore)),
kv: versioned.NewKV(ekv.MakeMemstore()),
previousNegotiations: make(map[id.ID]bool),
}
expected := make(map[id.ID]bool)
......@@ -339,7 +340,7 @@ func Test_marshalPreviousNegotiations_unmarshalPreviousNegotiations(t *testing.T
// loaded from storage via Store.saveNegotiationFingerprints and
// Store.loadNegotiationFingerprints.
func TestStore_saveNegotiationFingerprints_loadNegotiationFingerprints(t *testing.T) {
s := &Store{kv: versioned.NewKV(make(ekv.Memstore))}
s := &Store{kv: versioned.NewKV(ekv.MakeMemstore())}
rng := csprng.NewSystemRNG()
grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
......
......@@ -9,6 +9,12 @@ package store
import (
"bytes"
"io"
"math/rand"
"reflect"
"sort"
"testing"
"github.com/cloudflare/circl/dh/sidh"
"gitlab.com/elixxir/client/cmix/rounds"
sidhinterface "gitlab.com/elixxir/client/interfaces/sidh"
......@@ -26,12 +32,6 @@ import (
"gitlab.com/xx_network/crypto/large"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/netTime"
"io"
"math/rand"
"reflect"
"sort"
"testing"
"time"
)
type mockSentRequestHandler struct{}
......@@ -41,7 +41,7 @@ func (msrh *mockSentRequestHandler) Delete(sr *SentRequest) {}
// Happy path.
func TestNewOrLoadStore(t *testing.T) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(2))
_, err := NewOrLoadStore(kv, grp, &mockSentRequestHandler{})
......@@ -142,30 +142,30 @@ func TestStore_AddSent(t *testing.T) {
}
}
// Error path: request with request already exists in map.
func TestStore_AddSent_PartnerAlreadyExistsError(t *testing.T) {
s, _ := makeTestStore(t)
// // Error path: request with request already exists in map.
// func TestStore_AddSent_PartnerAlreadyExistsError(t *testing.T) {
// s, _ := makeTestStore(t)
rng := csprng.NewSystemRNG()
sidhPrivKey, sidhPubKey := genSidhAKeys(rng)
// rng := csprng.NewSystemRNG()
// sidhPrivKey, sidhPubKey := genSidhAKeys(rng)
partner := id.NewIdFromUInt(rand.Uint64(), id.User, t)
// partner := id.NewIdFromUInt(rand.Uint64(), id.User, t)
_, err := s.AddSent(partner, s.grp.NewInt(5), s.grp.NewInt(6),
s.grp.NewInt(7), sidhPrivKey, sidhPubKey,
format.Fingerprint{42}, true)
if err != nil {
t.Errorf("AddSent() produced an error: %+v", err)
}
// _, err := s.AddSent(partner, s.grp.NewInt(5), s.grp.NewInt(6),
// s.grp.NewInt(7), sidhPrivKey, sidhPubKey,
// format.Fingerprint{42}, true)
// if err != nil {
// t.Errorf("AddSent() produced an error: %+v", err)
// }
_, err = s.AddSent(partner, s.grp.NewInt(5), s.grp.NewInt(6),
s.grp.NewInt(7), sidhPrivKey, sidhPubKey,
format.Fingerprint{42}, true)
if err == nil {
t.Errorf("AddSent() did not produce the expected error for " +
"a request that already exists.")
}
}
// _, err = s.AddSent(partner, s.grp.NewInt(5), s.grp.NewInt(6),
// s.grp.NewInt(7), sidhPrivKey, sidhPubKey,
// format.Fingerprint{42}, true)
// if err == nil {
// t.Errorf("AddSent() did not produce the expected error for " +
// "a request that already exists.")
// }
// }
// Happy path.
func TestStore_AddReceived(t *testing.T) {
......@@ -869,7 +869,7 @@ func TestStore_DeleteAllRequests(t *testing.T) {
}
func makeTestStore(t *testing.T) (*Store, *versioned.KV) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
grp := cyclic.NewGroup(large.NewInt(173), large.NewInt(0))
store, err := NewOrLoadStore(kv, grp, &mockSentRequestHandler{})
......
......@@ -14,6 +14,7 @@ import (
"testing"
"time"
"gitlab.com/elixxir/client/api/messenger"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/ekv"
......@@ -25,12 +26,13 @@ import (
// Tests that Backup.InitializeBackup returns a new Backup with a copy of the
// key and the callback.
func Test_InitializeBackup(t *testing.T) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
cbChan := make(chan []byte, 2)
cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup }
expectedPassword := "MySuperSecurePassword"
b, err := InitializeBackup(expectedPassword, cb, &Container{}, newMockE2e(t),
b, err := InitializeBackup(expectedPassword, cb, &messenger.Container{},
newMockE2e(t),
newMockSession(t), newMockUserDiscovery(), kv, rngGen)
if err != nil {
t.Errorf("InitializeBackup returned an error: %+v", err)
......@@ -86,12 +88,12 @@ func Test_InitializeBackup(t *testing.T) {
// callback but keeps the password.
func Test_ResumeBackup(t *testing.T) {
// Start the first backup
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
cbChan1 := make(chan []byte)
cb1 := func(encryptedBackup []byte) { cbChan1 <- encryptedBackup }
expectedPassword := "MySuperSecurePassword"
b, err := InitializeBackup(expectedPassword, cb1, &Container{},
b, err := InitializeBackup(expectedPassword, cb1, &messenger.Container{},
newMockE2e(t), newMockSession(t), newMockUserDiscovery(), kv, rngGen)
if err != nil {
t.Errorf("Failed to initialize new Backup: %+v", err)
......@@ -113,7 +115,7 @@ func Test_ResumeBackup(t *testing.T) {
// Resume the backup with a new callback
cbChan2 := make(chan []byte)
cb2 := func(encryptedBackup []byte) { cbChan2 <- encryptedBackup }
b2, err := ResumeBackup(cb2, &Container{}, newMockE2e(t), newMockSession(t),
b2, err := ResumeBackup(cb2, &messenger.Container{}, newMockE2e(t), newMockSession(t),
newMockUserDiscovery(), kv, rngGen)
if err != nil {
t.Errorf("ResumeBackup returned an error: %+v", err)
......@@ -164,9 +166,9 @@ func Test_ResumeBackup(t *testing.T) {
// present in storage.
func Test_ResumeBackup_NoKeyError(t *testing.T) {
expectedErr := strings.Split(errLoadPassword, "%")[0]
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
_, err := ResumeBackup(nil, &Container{}, newMockE2e(t), newMockSession(t),
_, err := ResumeBackup(nil, &messenger.Container{}, newMockE2e(t), newMockSession(t),
newMockUserDiscovery(), kv, rngGen)
if err == nil || !strings.Contains(err.Error(), expectedErr) {
t.Errorf("ResumeBackup did not return the expected error when no "+
......@@ -420,11 +422,11 @@ func newTestBackup(password string, cb UpdateBackupFn, t *testing.T) *Backup {
b, err := InitializeBackup(
password,
cb,
&Container{},
&messenger.Container{},
newMockE2e(t),
newMockSession(t),
newMockUserDiscovery(),
versioned.NewKV(make(ekv.Memstore)),
versioned.NewKV(ekv.MakeMemstore()),
fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG),
)
if err != nil {
......@@ -437,13 +439,14 @@ func newTestBackup(password string, cb UpdateBackupFn, t *testing.T) *Backup {
// Tests that Backup.InitializeBackup returns a new Backup with a copy of the
// key and the callback.
func Benchmark_InitializeBackup(t *testing.B) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
rngGen := fastRNG.NewStreamGenerator(1000, 10, csprng.NewSystemRNG)
cbChan := make(chan []byte, 2)
cb := func(encryptedBackup []byte) { cbChan <- encryptedBackup }
expectedPassword := "MySuperSecurePassword"
for i := 0; i < t.N; i++ {
_, err := InitializeBackup(expectedPassword, cb, &Container{},
_, err := InitializeBackup(expectedPassword, cb,
&messenger.Container{},
newMockE2e(t),
newMockSession(t), newMockUserDiscovery(), kv, rngGen)
if err != nil {
......
package backup
import (
"testing"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/ekv"
"testing"
)
func Test_storeJson_loadJson(t *testing.T) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
json := "{'data': {'one': 1}}"
err := storeJson(json, kv)
......
......@@ -8,16 +8,17 @@
package backup
import (
"testing"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/ekv"
"gitlab.com/xx_network/primitives/netTime"
"testing"
)
// Tests that savePassword saves the password to storage by loading it and
// comparing it to the original.
func Test_savePassword(t *testing.T) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
expectedPassword := "MySuperSecurePassword"
// Save the password
......@@ -42,7 +43,7 @@ func Test_savePassword(t *testing.T) {
// Tests that loadPassword restores the original password saved to stage and
// compares it to the original.
func Test_loadPassword(t *testing.T) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
expectedPassword := "MySuperSecurePassword"
// Save the password
......@@ -71,7 +72,7 @@ func Test_loadPassword(t *testing.T) {
// Tests that deletePassword deletes the password from storage by trying to recover a
// deleted password.
func Test_deletePassword(t *testing.T) {
kv := versioned.NewKV(make(ekv.Memstore))
kv := versioned.NewKV(ekv.MakeMemstore())
expectedPassword := "MySuperSecurePassword"
// Save the password
......
......@@ -28,7 +28,7 @@ func (c *Client) ConnectWithAuthentication(recipientContact []byte, myIdentity [
if err != nil {
return nil, err
}
myID, rsaPriv, salt, myDHPriv, err := unmarshalIdentity(myIdentity)
myID, rsaPriv, salt, myDHPriv, err := c.unmarshalIdentity(myIdentity)
if err != nil {
return nil, err
}
......
......@@ -10,14 +10,14 @@ import (
"gitlab.com/elixxir/crypto/contact"
)
//connection tracker singleton, used to track connections so they can be
// connectionTrackerSingleton is used to track connections so they can be
// referenced by id back over the bindings
var connectionTrackerSingleton = &connectionTracker{
connections: make(map[int]*Connection),
count: 0,
}
//
// Connection is the bindings representation of a connect.Connection object that can be tracked
type Connection struct {
connection connect.Connection
id int
......@@ -27,13 +27,15 @@ type Connection struct {
// and returns a Connection object for the newly-created partner.Manager
// This function is to be used sender-side and will block until the
// partner.Manager is confirmed.
// recipientContact - marshalled contact.Contact object
// myIdentity - marshalled Identity object
func (c *Client) Connect(recipientContact []byte, myIdentity []byte) (
*Connection, error) {
cont, err := contact.Unmarshal(recipientContact)
if err != nil {
return nil, err
}
myID, _, _, myDHPriv, err := unmarshalIdentity(myIdentity)
myID, _, _, myDHPriv, err := c.unmarshalIdentity(myIdentity)
if err != nil {
return nil, err
}
......@@ -48,7 +50,7 @@ func (c *Client) Connect(recipientContact []byte, myIdentity []byte) (
return connectionTrackerSingleton.make(connection), nil
}
//
// E2ESendReport is the bindings representation of the return values of SendE2E
type E2ESendReport struct {
roundsList
MessageID []byte
......@@ -56,6 +58,7 @@ type E2ESendReport struct {
}
// SendE2E is a wrapper for sending specifically to the Connection's partner.Manager
// Returns marshalled E2ESendReport
func (c *Connection) SendE2E(mt int, payload []byte) ([]byte, error) {
rounds, mid, ts, err := c.connection.SendE2E(catalog.MessageType(mt), payload,
e2e2.GetDefaultParams())
......@@ -100,7 +103,7 @@ type listener struct {
l Listener
}
//
// Message is the bindings representation of a receive.Message
type Message struct {
MessageType int
ID []byte
......@@ -135,12 +138,12 @@ func (l listener) Hear(item receive.Message) {
l.l.Hear(result)
}
// Returns a name, used for debugging
// Name used for debugging
func (l listener) Name() string {
return l.l.Name()
}
//
// ListenerID represents the return type of RegisterListener
type ListenerID struct {
userID []byte
messageType int
......@@ -148,6 +151,7 @@ type ListenerID struct {
// RegisterListener is used for E2E reception
// and allows for reading data sent from the partner.Manager
// Returns marshalled ListenerID
func (c *Connection) RegisterListener(messageType int, newListener Listener) []byte {
listenerId := c.connection.RegisterListener(catalog.MessageType(messageType), listener{l: newListener})
newlistenerId := ListenerID{
......
......@@ -2,8 +2,10 @@ package bindings
import (
"encoding/json"
"gitlab.com/elixxir/crypto/contact"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/diffieHellman"
"gitlab.com/elixxir/primitives/fact"
"gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/crypto/xx"
"gitlab.com/xx_network/primitives/id"
......@@ -16,11 +18,6 @@ type Identity struct {
DHKeyPrivate []byte
}
type Fact struct {
Fact string
Type string
}
// MakeIdentity generates a new cryptographic identity for receving
// messages
func (c *Client) MakeIdentity() ([]byte, error) {
......@@ -46,7 +43,11 @@ func (c *Client) MakeIdentity() ([]byte, error) {
//make the ID
id, err := xx.NewID(rsaKey.GetPublic(),
salt, id.User)
if err != nil {
return nil, err
}
dhPrivJson, err := privkey.MarshalJSON()
if err != nil {
return nil, err
}
......@@ -56,35 +57,125 @@ func (c *Client) MakeIdentity() ([]byte, error) {
ID: id.Marshal(),
RSAPrivatePem: rsa.CreatePrivateKeyPem(rsaKey),
Salt: salt,
DHKeyPrivate: privkey.Bytes(),
DHKeyPrivate: dhPrivJson,
}
return json.Marshal(&I)
}
func GetContactFromIdentity(identity string) []byte {
I := Identity{}
func (c *Client) GetContactFromIdentity(identity []byte) ([]byte, error) {
uID, _, _, dhKey, err := c.unmarshalIdentity(identity)
if err != nil {
return nil, err
}
func unmarshalIdentity(marshaled []byte) (*id.ID, *rsa.PrivateKey, []byte,
grp := c.api.GetStorage().GetE2EGroup()
dhPub := grp.ExpG(dhKey, grp.NewInt(1))
ct := contact.Contact{
ID: uID,
DhPubKey: dhPub,
OwnershipProof: nil,
Facts: nil,
}
return ct.Marshal(), nil
}
func (c *Client) unmarshalIdentity(marshaled []byte) (*id.ID, *rsa.PrivateKey, []byte,
*cyclic.Int, error) {
return nil, nil, nil, nil, nil
I := Identity{}
err := json.Unmarshal(marshaled, &I)
if err != nil {
return nil, nil, nil, nil, err
}
uID, err := id.Unmarshal(I.ID)
if err != nil {
return nil, nil, nil, nil, err
}
dhkey := c.api.GetStorage().GetE2EGroup().NewInt(1)
err = dhkey.UnmarshalJSON(I.DHKeyPrivate)
if err != nil {
return nil, nil, nil, nil, err
}
rsaPriv, err := rsa.LoadPrivateKeyFromPem(I.RSAPrivatePem)
if err != nil {
return nil, nil, nil, nil, err
}
return uID, rsaPriv, I.Salt, dhkey, nil
}
func GetIDFromContact(marshaled []byte) ([]byte, error) {
cnt, err := contact.Unmarshal(marshaled)
if err != nil {
return nil, err
}
return cnt.ID.Marshal(), nil
}
func GetPubkeyFromContact(marshaled []byte) ([]byte, error) {
cnt, err := contact.Unmarshal(marshaled)
if err != nil {
return nil, err
}
return cnt.ID.Marshal(), nil
}
type Fact struct {
Fact string
Type int
}
// SetFactsOnContact replaces the facts on the contact with the passed in facts
// pass in empty facts in order to clear the facts
func SetFactsOnContact(contact []byte, facts []byte) []byte {
I := Identity{}
func SetFactsOnContact(marshaled []byte, facts []byte) ([]byte, error) {
cnt, err := contact.Unmarshal(marshaled)
if err != nil {
return nil, err
}
func GetIDFromContact(contact []byte) []byte {
factsList := make([]Fact, 0)
err = json.Unmarshal(facts, &factsList)
if err != nil {
return nil, err
}
realFactList := make(fact.FactList, 0, len(factsList))
for i := range factsList {
realFactList = append(realFactList, fact.Fact{
Fact: factsList[i].Fact,
T: fact.FactType(factsList[i].Type),
})
}
func GetPubkeyFromContact(contact []byte) []byte {
cnt.Facts = realFactList
return cnt.Marshal(), nil
}
func GetFactsFromContact(marshaled []byte) ([]byte, error) {
cnt, err := contact.Unmarshal(marshaled)
if err != nil {
return nil, err
}
func GetFactsFromContact(contact []byte) []byte {
factsList := make([]Fact, len(cnt.Facts))
for i := range cnt.Facts {
factsList = append(factsList, Fact{
Fact: cnt.Facts[i].Fact,
Type: int(cnt.Facts[i].T),
})
}
factsListMarshaled, err := json.Marshal(&factsList)
if err != nil {
return nil, err
}
return factsListMarshaled, nil
}
package bindings
import (
"encoding/json"
"fmt"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/cmix"
"gitlab.com/xx_network/primitives/id"
"time"
)
type roundsList struct {
rounds []int
type roundsList []int
func (rl roundsList) Marshal() ([]byte, error) {
return json.Marshal(&rl)
}
func unmarshalRoundsList(marshaled []byte) ([]id.Round, error) {
rl := roundsList{}
err := json.Unmarshal(marshaled, &rl)
if err != nil {
return nil, err
}
func (rl roundsList) Marshal() []byte {
realRl := make([]id.Round, len(rl))
for _, rid := range rl {
realRl = append(realRl, id.Round(rid))
}
func unmarshalRoundsList(marshaled []byte) []id.Round {
return realRl, nil
}
func makeRoundsList(rounds []id.Round) roundsList {
rl := make(roundsList, 0, len(rounds))
for _, rid := range rounds {
rl = append(rl, int(rid))
}
return rl
}
// MessageDeliveryCallback gets called on the determination if all events
// related to a message send were successful.
type MessageDeliveryCallback interface {
EventCallback(delivered, timedOut bool, roundResults []byte)
}
// WaitForMessageDelivery allows the caller to get notified if the rounds a
......@@ -34,39 +57,39 @@ func makeRoundsList(rounds []id.Round) roundsList {
// This function takes the marshaled send report to ensure a memory leak does
// not occur as a result of both sides of the bindings holding a reference to
// the same pointer.
func (c *Client) WaitForMessageDelivery(marshaledSendReport []byte,
func (c *Client) WaitForMessageDelivery(roundList []byte,
mdc MessageDeliveryCallback, timeoutMS int) error {
jww.INFO.Printf("WaitForMessageDelivery(%v, _, %v)",
marshaledSendReport, timeoutMS)
sr, err := UnmarshalSendReport(marshaledSendReport)
roundList, timeoutMS)
rl, err := unmarshalRoundsList(roundList)
if err != nil {
return errors.New(fmt.Sprintf("Failed to "+
"WaitForMessageDelivery callback due to bad Send Report: %+v", err))
}
if sr == nil || sr.rl == nil || len(sr.rl.list) == 0 {
if rl == nil || len(rl) == 0 {
return errors.New(fmt.Sprintf("Failed to "+
"WaitForMessageDelivery callback due to invalid Send Report "+
"unmarshal: %s", string(marshaledSendReport)))
"unmarshal: %s", string(roundList)))
}
f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundLookupStatus) {
results := make([]byte, len(sr.rl.list))
f := func(allRoundsSucceeded, timedOut bool, rounds map[id.Round]cmix.RoundResult) {
results := make([]byte, len(rl))
jww.INFO.Printf("Processing WaitForMessageDelivery report "+
"for %v, success: %v, timedout: %v", sr.mid, allRoundsSucceeded,
"success: %v, timedout: %v", allRoundsSucceeded,
timedOut)
for i, r := range sr.rl.list {
for i, r := range rl {
if result, exists := rounds[r]; exists {
results[i] = byte(result)
results[i] = byte(result.Status)
}
}
mdc.EventCallback(sr.mid.Marshal(), allRoundsSucceeded, timedOut, results)
mdc.EventCallback(allRoundsSucceeded, timedOut, results)
}
timeout := time.Duration(timeoutMS) * time.Millisecond
err = c.api.GetRoundResults(sr.rl.list, timeout, f)
err = c.api.GetCmix().GetRoundResults(timeout, f, rl...)
return err
}
# Client Bindings
"bindings" is the client bindings which can be used to generate Android
and iOS client libraries for apps using gomobile. Gomobile is
limited to int, string, []byte, interfaces, and only a couple other types, so
it is necessary to define several interfaces to support passing more complex
data across the boundary (see `interfaces.go`). The rest of the logic
is located in `api.go`
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package old
import (
"fmt"
"gitlab.com/elixxir/crypto/contact"
"gitlab.com/xx_network/primitives/id"
)
// Create an insecure e2e relationship with a precanned user
func (c *Client) MakePrecannedAuthenticatedChannel(precannedID int) (*Contact, error) {
precannedContact, err := c.api.MakePrecannedAuthenticatedChannel(uint(precannedID))
if err != nil {
return nil, fmt.Errorf("Failed to "+
"MakePrecannedAuthenticatedChannel: %+v", err)
}
return &Contact{c: &precannedContact}, nil
}
// RequestAuthenticatedChannel sends a request to another party to establish an
// authenticated channel
// It will not run if the network status is not healthy
// An error will be returned if a channel already exists, if a request was
// already received.
// When a confirmation occurs, the channel will be created and the callback
// will be called
// This can be called many times and retried.
//
// This function takes the marshaled send report to ensure a memory leak does
// not occur as a result of both sides of the bindings holding a refrence to
// the same pointer.
func (c *Client) RequestAuthenticatedChannel(recipientMarshaled,
meMarshaled []byte, message string) (int, error) {
recipent, err := contact.Unmarshal(recipientMarshaled)
if err != nil {
return 0, fmt.Errorf("Failed to "+
"RequestAuthenticatedChannel: Failed to Unmarshal Recipent: "+
"%+v", err)
}
me, err := contact.Unmarshal(meMarshaled)
if err != nil {
return 0, fmt.Errorf("Failed to "+
"RequestAuthenticatedChannel: Failed to Unmarshal Me: %+v", err)
}
rid, err := c.api.RequestAuthenticatedChannel(recipent, me, message)
return int(rid), err
}
// ResetSession resets an authenticated channel that already exists
func (c *Client) ResetSession(recipientMarshaled,
meMarshaled []byte, message string) (int, error) {
recipent, err := contact.Unmarshal(recipientMarshaled)
if err != nil {
return 0, fmt.Errorf("failed to "+
"ResetSession: failed to Unmarshal Recipent: "+
"%+v", err)
}
me, err := contact.Unmarshal(meMarshaled)
if err != nil {
return 0, fmt.Errorf("failed to "+
"ResetSession: Failed to Unmarshal Me: %+v", err)
}
rid, err := c.api.ResetSession(recipent, me, message)
return int(rid), err
}
// RegisterAuthCallbacks registers all callbacks for authenticated channels.
// This can only be called once
func (c *Client) RegisterAuthCallbacks(request AuthRequestCallback,
confirm AuthConfirmCallback, reset AuthResetNotificationCallback) {
requestFunc := func(requestor contact.Contact) {
requestorBind := &Contact{c: &requestor}
request.Callback(requestorBind)
}
resetFunc := func(resetor contact.Contact) {
resetorBind := &Contact{c: &resetor}
reset.Callback(resetorBind)
}
confirmFunc := func(partner contact.Contact) {
partnerBind := &Contact{c: &partner}
confirm.Callback(partnerBind)
}
c.api.GetAuthRegistrar().AddGeneralConfirmCallback(confirmFunc)
c.api.GetAuthRegistrar().AddGeneralRequestCallback(requestFunc)
c.api.GetAuthRegistrar().AddResetNotificationCallback(resetFunc)
}
// ConfirmAuthenticatedChannel creates an authenticated channel out of a valid
// received request and sends a message to the requestor that the request has
// been confirmed
// It will not run if the network status is not healthy
// An error will be returned if a request doest
// exist, or if the passed in contact does not exactly match the received
// request.
// This can be called many times and retried.
//
// This function takes the marshaled send report to ensure a memory leak does
// not occur as a result of both sides of the bindings holding a refrence to
// the same pointer.
func (c *Client) ConfirmAuthenticatedChannel(recipientMarshaled []byte) (int, error) {
recipent, err := contact.Unmarshal(recipientMarshaled)
if err != nil {
return 0, fmt.Errorf("Failed to "+
"ConfirmAuthenticatedChannel: Failed to Unmarshal Recipient: "+
"%+v", err)
}
rid, err := c.api.ConfirmAuthenticatedChannel(recipent)
return int(rid), err
}
// VerifyOwnership checks if the ownership proof on a passed contact matches the
// identity in a verified contact
func (c *Client) VerifyOwnership(receivedMarshaled, verifiedMarshaled []byte) (bool, error) {
received, err := contact.Unmarshal(receivedMarshaled)
if err != nil {
return false, fmt.Errorf("Failed to "+
"VerifyOwnership: Failed to Unmarshal Received: %+v", err)
}
verified, err := contact.Unmarshal(verifiedMarshaled)
if err != nil {
return false, fmt.Errorf("Failed to "+
"VerifyOwnership: Failed to Unmarshal Verified: %+v", err)
}
return c.api.VerifyOwnership(received, verified), nil
}
// GetRelationshipFingerprint returns a unique 15 character fingerprint for an
// E2E relationship. An error is returned if no relationship with the partner
// is found.
func (c *Client) GetRelationshipFingerprint(partnerID []byte) (string, error) {
partner, err := id.Unmarshal(partnerID)
if err != nil {
return "", err
}
return c.api.GetRelationshipFingerprint(partner)
}
// ReplayRequests Resends all pending requests over the normal callbacks
func (c *Client) ReplayRequests() {
c.api.GetAuthRegistrar().ReplayRequests()
}
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
////////////////////////////////////////////////////////////////////////////////
package old
import (
"gitlab.com/elixxir/client/backup"
)
type Backup struct {
b *backup.Backup
}
// UpdateBackupFunc contains a function callback that returns new backups.
type UpdateBackupFunc interface {
UpdateBackup(encryptedBackup []byte)
}
// InitializeBackup starts the backup processes that returns backup updates when
// they occur. Any time an event occurs that changes the contents of the backup,
// such as adding or deleting a contact, the backup is triggered and an
// encrypted backup is generated and returned on the updateBackupCb callback.
// Call this function only when enabling backup if it has not already been
// initialized or when the user wants to change their password.
// To resume backup process on app recovery, use ResumeBackup.
func InitializeBackup(
password string, updateBackupCb UpdateBackupFunc, c *Client) (*Backup, error) {
b, err := backup.InitializeBackup(
password, updateBackupCb.UpdateBackup, &c.api)
if err != nil {
return nil, err
}
return &Backup{b}, nil
}
// ResumeBackup starts the backup processes back up with a new callback after it
// has been initialized.
// Call this function only when resuming a backup that has already been
// initialized or to replace the callback.
// To start the backup for the first time or to use a new password, use
// InitializeBackup.
func ResumeBackup(cb UpdateBackupFunc, c *Client) (
*Backup, error) {
b, err := backup.ResumeBackup(cb.UpdateBackup, &c.api)
if err != nil {
return nil, err
}
return &Backup{b}, nil
}
// StopBackup stops the backup processes and deletes the user's password from
// storage. To enable backups again, call InitializeBackup.
func (b *Backup) StopBackup() error {
return b.b.StopBackup()
}
// IsBackupRunning returns true if the backup has been initialized and is
// running. Returns false if it has been stopped.
func (b *Backup) IsBackupRunning() bool {
return b.b.IsBackupRunning()
}
// AddJson stores a passed in json string in the backup structure
func (b *Backup) AddJson(json string) {
b.b.AddJson(json)
}
///////////////////////////////////////////////////////////////////////////////
// Copyright © 2020 xx network SEZC //
// //
// Use of this source code is governed by a license that can be found in the //
// LICENSE file //
///////////////////////////////////////////////////////////////////////////////
package old
import (
"gitlab.com/elixxir/client/interfaces"
"gitlab.com/elixxir/client/switchboard"
"gitlab.com/elixxir/comms/network/dataStructures"
"gitlab.com/xx_network/primitives/id"
)
// Listener provides a callback to hear a message
// An object implementing this interface can be called back when the client
// gets a message of the type that the registerer specified at registration
// time.
type Listener interface {
// Hear is called to receive a message in the UI
Hear(message *Message)
// Returns a name, used for debugging
Name() string
}
// A callback when which is used to receive notification if network health
// changes
type NetworkHealthCallback interface {
Callback(bool)
}
// RoundEventCallback handles waiting on the exact state of a round on
// the cMix network.
type RoundEventCallback interface {
EventCallback(rid, state int, timedOut bool)
}
// RoundCompletionCallback is returned when the completion of a round is known.
type RoundCompletionCallback interface {
EventCallback(rid int, success, timedOut bool)
}
// MessageDeliveryCallback gets called on the determination if all events
// related to a message send were successful.
type MessageDeliveryCallback interface {
EventCallback(msgID []byte, delivered, timedOut bool, roundResults []byte)
}
// AuthRequestCallback notifies the register whenever they receive an auth
// request
type AuthRequestCallback interface {
Callback(requestor *Contact)
}
// AuthConfirmCallback notifies the register whenever they receive an auth
// request confirmation
type AuthConfirmCallback interface {
Callback(partner *Contact)
}
// AuthRequestCallback notifies the register whenever they receive an auth
// request
type AuthResetNotificationCallback interface {
Callback(requestor *Contact)
}
// Generic Unregister - a generic return used for all callbacks which can be
// unregistered
// Interface which allows the un-registration of a listener
type Unregister struct {
f func()
}
//Call unregisters a callback
func (u *Unregister) Unregister() {
u.f()
}
//creates an unregister interface for listeners
func newListenerUnregister(lid switchboard.ListenerID, sw interfaces.Switchboard) *Unregister {
f := func() {
sw.Unregister(lid)
}
return &Unregister{f: f}
}
//creates an unregister interface for round events
func newRoundUnregister(rid id.Round, ec *dataStructures.EventCallback,
re interfaces.RoundEvents) *Unregister {
f := func() {
re.Remove(rid, ec)
}
return &Unregister{f: f}
}
//creates an unregister interface for round events
func newRoundListUnregister(rounds []id.Round, ec []*dataStructures.EventCallback,
re interfaces.RoundEvents) *Unregister {
f := func() {
for i, r := range rounds {
re.Remove(r, ec[i])
}
}
return &Unregister{f: f}
}
type ClientError interface {
Report(source, message, trace string)
}
type LogWriter interface {
Log(string)
}
type writerAdapter struct {
lw LogWriter
}
func (wa *writerAdapter) Write(p []byte) (n int, err error) {
wa.lw.Log(string(p))
return len(p), nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment