Skip to content
Snippets Groups Projects
Commit dbdcbade authored by Benjamin Wenger's avatar Benjamin Wenger
Browse files

finished contacts, added precanned authenticated channel creation,

made new API not return a client, forced a load
parent a68fa241
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,7 @@ package api ...@@ -3,6 +3,7 @@ package api
import ( import (
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/interfaces/contact" "gitlab.com/elixxir/client/interfaces/contact"
"gitlab.com/elixxir/client/storage/e2e"
) )
// CreateAuthenticatedChannel creates a 1-way authenticated channel // CreateAuthenticatedChannel creates a 1-way authenticated channel
...@@ -29,3 +30,35 @@ func (c *Client) RegisterAuthRequestCb(cb func(contact contact.Contact, ...@@ -29,3 +30,35 @@ func (c *Client) RegisterAuthRequestCb(cb func(contact contact.Contact,
payload []byte)) { payload []byte)) {
jww.INFO.Printf("RegisterAuthRequestCb(...)") jww.INFO.Printf("RegisterAuthRequestCb(...)")
} }
// Create an insecure e2e relationship with a precanned user
func (c *Client) MakePrecannedAuthenticatedChannel(precannedID uint) contact.Contact {
precan := c.MakePrecannedContact(precannedID)
//add the precanned user as a e2e contact
sesParam := e2e.GetDefaultSessionParams()
c.storage.E2e().AddPartner(precan.ID, precan.DhPubKey, sesParam, sesParam)
return precan
}
// Create an insecure e2e contact object for a precanned user
func (c *Client) MakePrecannedContact(precannedID uint) contact.Contact {
e2eGrp := c.storage.E2e().GetGroup()
//get the user definition
precanned := createPrecannedUser(precannedID, c.rng.GetStream(),
c.storage.Cmix().GetGroup(), e2eGrp)
//compute their public e2e key
partnerPubKey := e2eGrp.ExpG(precanned.E2eDhPrivateKey, e2eGrp.NewInt(1))
return contact.Contact{
ID: precanned.ID,
DhPubKey: partnerPubKey,
OwnershipProof: nil,
Facts: make([]contact.Fact, 0),
}
}
\ No newline at end of file
...@@ -56,7 +56,7 @@ type Client struct { ...@@ -56,7 +56,7 @@ type Client struct {
// with the network. Note that this does not register a username/identity, but // with the network. Note that this does not register a username/identity, but
// merely creates a new cryptographic identity for adding such information // merely creates a new cryptographic identity for adding such information
// at a later date. // at a later date.
func NewClient(ndfJSON, storageDir string, password []byte, registrationCode string) (*Client, error) { func NewClient(ndfJSON, storageDir string, password []byte, registrationCode string) error {
// Use fastRNG for RNG ops (AES fortuna based RNG using system RNG) // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG) rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
rngStream := rngStreamGen.GetStream() rngStream := rngStreamGen.GetStream()
...@@ -64,7 +64,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str ...@@ -64,7 +64,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str
// Parse the NDF // Parse the NDF
def, err := parseNDF(ndfJSON) def, err := parseNDF(ndfJSON)
if err != nil { if err != nil {
return nil, err return err
} }
cmixGrp, e2eGrp := decodeGroups(def) cmixGrp, e2eGrp := decodeGroups(def)
...@@ -75,7 +75,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str ...@@ -75,7 +75,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str
storageSess, err := storage.New(storageDir, passwordStr, protoUser, storageSess, err := storage.New(storageDir, passwordStr, protoUser,
cmixGrp, e2eGrp, rngStreamGen) cmixGrp, e2eGrp, rngStreamGen)
if err != nil { if err != nil {
return nil, err return err
} }
// Save NDF to be used in the future // Save NDF to be used in the future
...@@ -87,12 +87,12 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str ...@@ -87,12 +87,12 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str
//move the registration state to keys generated //move the registration state to keys generated
err = storageSess.ForwardRegistrationStatus(storage.KeyGenComplete) err = storageSess.ForwardRegistrationStatus(storage.KeyGenComplete)
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "Failed to denote state "+ return errors.WithMessage(err, "Failed to denote state "+
"change in session") "change in session")
} }
//execute the rest of the loading as normal //TODO: close the session
return loadClient(storageSess, rngStreamGen) return nil
} }
// NewPrecannedClient creates an insecure user with predetermined keys with nodes // NewPrecannedClient creates an insecure user with predetermined keys with nodes
...@@ -100,7 +100,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str ...@@ -100,7 +100,7 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str
// with the network. Note that this does not register a username/identity, but // with the network. Note that this does not register a username/identity, but
// merely creates a new cryptographic identity for adding such information // merely creates a new cryptographic identity for adding such information
// at a later date. // at a later date.
func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password []byte) (*Client, error) { func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password []byte) error {
// Use fastRNG for RNG ops (AES fortuna based RNG using system RNG) // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG) rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
rngStream := rngStreamGen.GetStream() rngStream := rngStreamGen.GetStream()
...@@ -108,7 +108,7 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [ ...@@ -108,7 +108,7 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [
// Parse the NDF // Parse the NDF
def, err := parseNDF(defJSON) def, err := parseNDF(defJSON)
if err != nil { if err != nil {
return nil, err return err
} }
cmixGrp, e2eGrp := decodeGroups(def) cmixGrp, e2eGrp := decodeGroups(def)
...@@ -119,7 +119,7 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [ ...@@ -119,7 +119,7 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [
storageSess, err := storage.New(storageDir, passwordStr, protoUser, storageSess, err := storage.New(storageDir, passwordStr, protoUser,
cmixGrp, e2eGrp, rngStreamGen) cmixGrp, e2eGrp, rngStreamGen)
if err != nil { if err != nil {
return nil, err return err
} }
// Save NDF to be used in the future // Save NDF to be used in the future
...@@ -128,12 +128,12 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [ ...@@ -128,12 +128,12 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [
//move the registration state to keys generated //move the registration state to keys generated
err = storageSess.ForwardRegistrationStatus(storage.KeyGenComplete) err = storageSess.ForwardRegistrationStatus(storage.KeyGenComplete)
if err != nil { if err != nil {
return nil, errors.WithMessage(err, "Failed to denote state "+ return errors.WithMessage(err, "Failed to denote state "+
"change in session") "change in session")
} }
//execute the rest of the loading as normal //TODO: close the session
return loadClient(storageSess, rngStreamGen) return nil
} }
// LoadClient initalizes a client object from existing storage. // LoadClient initalizes a client object from existing storage.
......
...@@ -128,7 +128,7 @@ var rootCmd = &cobra.Command{ ...@@ -128,7 +128,7 @@ var rootCmd = &cobra.Command{
storeDir := viper.GetString("session") storeDir := viper.GetString("session")
regCode := viper.GetString("regcode") regCode := viper.GetString("regcode")
var client *api.Client //create a new client if none exist
if _, err := os.Stat(storeDir); os.IsNotExist(err) { if _, err := os.Stat(storeDir); os.IsNotExist(err) {
// Load NDF // Load NDF
ndfPath := viper.GetString("ndf") ndfPath := viper.GetString("ndf")
...@@ -137,22 +137,23 @@ var rootCmd = &cobra.Command{ ...@@ -137,22 +137,23 @@ var rootCmd = &cobra.Command{
jww.FATAL.Panicf(err.Error()) jww.FATAL.Panicf(err.Error())
} }
client, err = api.NewClient(string(ndfJSON), storeDir, err = api.NewClient(string(ndfJSON), storeDir,
[]byte(pass), regCode) []byte(pass), regCode)
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
} else { }
client, err = api.LoadClient(storeDir, []byte(pass))
//load the client
client, err := api.LoadClient(storeDir, []byte(pass))
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
}
user := client.GetUser() user := client.GetUser()
jww.INFO.Printf("%s", user.ID) jww.INFO.Printf("%s", user.ID)
err := client.StartNetworkFollower() err = client.StartNetworkFollower()
if err != nil { if err != nil {
jww.FATAL.Panicf("%+v", err) jww.FATAL.Panicf("%+v", err)
} }
......
...@@ -3,13 +3,18 @@ package interfaces ...@@ -3,13 +3,18 @@ package interfaces
type Contact interface { type Contact interface {
GetID() []byte GetID() []byte
GetDHPublicKey() []byte GetDHPublicKey() []byte
AddFact(Fact) Contact GetOwnershipProof() []byte
NumFacts() int GetFactList() FactList
GetFact(int) (Fact, error)
Marshal() ([]byte, error) Marshal() ([]byte, error)
} }
type FactList interface {
Num() int
Get(int) Fact
Add(string, int) error
}
type Fact interface { type Fact interface {
Get() string Get() string
GetType() int Type() int
} }
...@@ -4,7 +4,6 @@ import ( ...@@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/elixxir/client/interfaces" "gitlab.com/elixxir/client/interfaces"
"gitlab.com/elixxir/client/interfaces/contact/fact"
"gitlab.com/elixxir/crypto/cyclic" "gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/xx_network/primitives/id" "gitlab.com/xx_network/primitives/id"
) )
...@@ -15,7 +14,8 @@ import ( ...@@ -15,7 +14,8 @@ import (
type Contact struct { type Contact struct {
ID *id.ID ID *id.ID
DhPubKey *cyclic.Int DhPubKey *cyclic.Int
Facts []fact.Fact OwnershipProof []byte
Facts []Fact
} }
// GetID returns the user ID for this user. // GetID returns the user ID for this user.
...@@ -23,32 +23,19 @@ func (c Contact) GetID() []byte { ...@@ -23,32 +23,19 @@ func (c Contact) GetID() []byte {
return c.ID.Bytes() return c.ID.Bytes()
} }
// GetPublicKey returns the publickey bytes for this user. // GetDHPublicKey returns the public key associated with the Contact.
func (c Contact) GetDHPublicKey() []byte { func (c Contact) GetDHPublicKey() []byte {
return c.DhPubKey.Bytes() return c.DhPubKey.Bytes()
} }
// Adds a fact to the contact. Because the contact is pass by value, this makes // GetDHPublicKey returns hash of a DH proof of key ownership.
// a new copy with the fact func (c Contact) GetOwnershipProof() []byte {
func (c Contact) AddFact(f interfaces.Fact) interfaces.Contact { return c.OwnershipProof
fNew := fact.Fact{
Fact: f.Get(),
T: fact.Type(f.GetType()),
}
c.Facts = append(c.Facts, fNew)
return c
}
func (c Contact) NumFacts() int {
return len(c.Facts)
} }
func (c Contact) GetFact(i int) (interfaces.Fact, error) { // Returns a fact list for adding and getting facts to and from the contact
if i >= len(c.Facts) || i < 0 { func (c Contact) GetFactList() interfaces.FactList {
return nil, errors.Errorf("Cannot get a a fact at position %v, "+ return FactList{source: &c}
"only %v facts", i, len(c.Facts))
}
return c.Facts[i], nil
} }
func (c Contact) Marshal() ([]byte, error) { func (c Contact) Marshal() ([]byte, error) {
......
package fact package contact
import ( import (
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/elixxir/client/interfaces"
) )
type Fact struct { type Fact struct {
Fact string Fact string
T Type T FactType
} }
func (f Fact) Get() string { func (f Fact) Get() string {
return f.Fact return f.Fact
} }
func (f Fact) GetType() int { func (f Fact) Type() int {
return int(f.T) return int(f.T)
} }
func (f Fact) Copy() interfaces.Fact {
f2 := Fact{
Fact: f.Fact,
T: f.T,
}
return &f2
}
// marshal is for transmission for UDB, not a part of the fact interface // marshal is for transmission for UDB, not a part of the fact interface
func (f Fact) Marshal() []byte { func (f Fact) Marshal() []byte {
serial := []byte(f.Fact) serial := []byte(f.Fact)
...@@ -36,8 +27,8 @@ func (f Fact) Marshal() []byte { ...@@ -36,8 +27,8 @@ func (f Fact) Marshal() []byte {
return b return b
} }
func Unmarshal(b []byte) (Fact, error) { func UnmarshalFact(b []byte) (Fact, error) {
t := Type(b[0]) t := FactType(b[0])
if !t.IsValid() { if !t.IsValid() {
return Fact{}, errors.Errorf("Fact is not a valid type: %s", t) return Fact{}, errors.Errorf("Fact is not a valid type: %s", t)
} }
......
package contact
import (
"github.com/pkg/errors"
"gitlab.com/elixxir/client/interfaces"
)
type FactList struct {
source *Contact
}
func (fl FactList) Num() int {
return len(fl.source.Facts)
}
func (fl FactList) Get(i int) interfaces.Fact {
return fl.source.Facts[i]
}
func (fl FactList) Add(fact string, factType int) error {
ft := FactType(factType)
if !ft.IsValid() {
return errors.New("Invalid fact type")
}
fl.source.Facts = append(fl.source.Facts, Fact{
Fact: fact,
T: ft,
})
return nil
}
package fact package contact
import "fmt" import "fmt"
type Type uint8 type FactType uint8
const ( const (
Username Type = 0 Username FactType = 0
Email Type = 1 Email FactType = 1
Phone Type = 2 Phone FactType = 2
) )
func (t Type) String() string { func (t FactType) String() string {
switch t { switch t {
case Username: case Username:
return "Username" return "Username"
...@@ -19,10 +19,10 @@ func (t Type) String() string { ...@@ -19,10 +19,10 @@ func (t Type) String() string {
case Phone: case Phone:
return "Phone" return "Phone"
default: default:
return fmt.Sprintf("Unknown Fact Type: %d", t) return fmt.Sprintf("Unknown Fact FactType: %d", t)
} }
} }
func (t Type) IsValid() bool { func (t FactType) IsValid() bool {
return t == Username || t == Email || t == Phone return t == Username || t == Email || t == Phone
} }
...@@ -64,6 +64,6 @@ func (u User) GetContact() interfaces.Contact { ...@@ -64,6 +64,6 @@ func (u User) GetContact() interfaces.Contact {
return contact.Contact{ return contact.Contact{
ID: u.ID.DeepCopy(), ID: u.ID.DeepCopy(),
DhPubKey: u.E2eDhPublicKey, DhPubKey: u.E2eDhPublicKey,
Facts: nil, Facts: make([]contact.Fact, 0),
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment