diff --git a/api/client.go b/api/client.go
index bc460a17df20e7d5eebda5344843665ddfcb38eb..a6cf414bc76ea7a4807c1dc804af9e4fce25b12d 100644
--- a/api/client.go
+++ b/api/client.go
@@ -8,6 +8,7 @@
package api
import (
+ "encoding/json"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/auth"
@@ -72,7 +73,8 @@ type Client struct {
// with the network. Note that this does not register a username/identity, but
// merely creates a new cryptographic identity for adding such information
// at a later date.
-func NewClient(ndfJSON, storageDir string, password []byte, registrationCode string) error {
+func NewClient(ndfJSON, storageDir string, password []byte,
+ registrationCode string) error {
jww.INFO.Printf("NewClient(dir: %s)", storageDir)
// Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
@@ -103,7 +105,8 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str
// with the network. Note that this does not register a username/identity, but
// merely creates a new cryptographic identity for adding such information
// at a later date.
-func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password []byte) error {
+func NewPrecannedClient(precannedID uint, defJSON, storageDir string,
+ password []byte) error {
jww.INFO.Printf("NewPrecannedClient()")
// Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
@@ -132,7 +135,8 @@ func NewPrecannedClient(precannedID uint, defJSON, storageDir string, password [
// with the network. Note that this does not register a username/identity, but
// merely creates a new cryptographic identity for adding such information
// at a later date.
-func NewVanityClient(ndfJSON, storageDir string, password []byte, registrationCode string, userIdPrefix string) error {
+func NewVanityClient(ndfJSON, storageDir string, password []byte,
+ registrationCode string, userIdPrefix string) error {
jww.INFO.Printf("NewVanityClient()")
// Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
@@ -193,6 +197,45 @@ func OpenClient(storageDir string, password []byte, parameters params.Network) (
return c, nil
}
+// NewProtoClient_Unsafe initializes a client object from a JSON containing
+// predefined cryptographic which defines a user. This is designed for some
+// specific deployment procedures and is generally unsafe.
+func NewProtoClient_Unsafe(storageDir string, password []byte,
+ protoClientJSON []byte,
+ parameters params.Network, def *ndf.NetworkDefinition) (*Client, error) {
+ // Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
+ rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
+
+ cmixGrp, e2eGrp := decodeGroups(def)
+
+ // Pull the proto user from the JSON
+ protoUser := &user.Proto{}
+ err := json.Unmarshal(protoClientJSON, protoUser)
+ if err != nil {
+ return nil, err
+ }
+
+ // Initialize a user object for storage set up
+ usr := user.NewUserFromProto(protoUser)
+
+ // Set up storage
+ err = checkVersionAndSetupStorage(def, storageDir, password, usr,
+ cmixGrp, e2eGrp, rngStreamGen, false, protoUser.RegCode)
+
+ //Open the client
+ c, err := OpenClient(storageDir, password, parameters)
+ if err != nil {
+ return nil, err
+ }
+
+ // Set registration values in storage
+ c.GetStorage().User().SetReceptionRegistrationValidationSignature(protoUser.ReceptionRegValidationSig)
+ c.GetStorage().User().SetTransmissionRegistrationValidationSignature(protoUser.TransmissionRegValidationSig)
+ c.GetStorage().User().SetRegistrationTimestamp(protoUser.RegistrationTimestamp.UnixNano())
+
+ return c, nil
+}
+
// Login initializes a client object from existing storage.
func Login(storageDir string, password []byte, parameters params.Network) (*Client, error) {
jww.INFO.Printf("Login()")
@@ -234,7 +277,8 @@ func Login(storageDir string, password []byte, parameters params.Network) (*Clie
hp.KaClientOpts.Time = time.Duration(math.MaxInt64)
hp.AuthEnabled = false
hp.MaxRetries = 5
- _, err = c.comms.AddHost(&id.NotificationBot, def.Notification.Address, []byte(def.Notification.TlsCertificate), hp)
+ _, err = c.comms.AddHost(&id.NotificationBot, def.Notification.Address,
+ []byte(def.Notification.TlsCertificate), hp)
if err != nil {
jww.WARN.Printf("Failed adding host for notifications: %+v", err)
}
@@ -262,7 +306,7 @@ func Login(storageDir string, password []byte, parameters params.Network) (*Clie
// LoginWithNewBaseNDF_UNSAFE initializes a client object from existing storage
// while replacing the base NDF. This is designed for some specific deployment
// procedures and is generally unsafe.
-func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte,
+func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte, protoClientJSON []byte,
newBaseNdf string, parameters params.Network) (*Client, error) {
jww.INFO.Printf("LoginWithNewBaseNDF_UNSAFE()")
@@ -273,8 +317,7 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte,
}
//Open the client
- c, err := OpenClient(storageDir, password, parameters)
-
+ c, err := NewProtoClient_Unsafe(storageDir, password, protoClientJSON, parameters, def)
if err != nil {
return nil, err
}
@@ -288,18 +331,6 @@ func LoginWithNewBaseNDF_UNSAFE(storageDir string, password []byte,
//store the updated base NDF
c.storage.SetNDF(def)
- //initialize registration
- if def.Registration.Address != "" {
- err = c.initPermissioning(def)
- if err != nil {
- return nil, err
- }
- } else {
- jww.WARN.Printf("Registration with permissioning skipped due to " +
- "blank permissionign address. Client will not be able to register " +
- "or track network.")
- }
-
// Initialize network and link it to context
c.network, err = network.NewManager(c.storage, c.switchboard, c.rng,
c.events, c.comms, parameters, def)
diff --git a/api/user.go b/api/user.go
index ef8eb1092ee61e8e766c00d2979cb4c20d108d82..1b22a0877235636c55bbd2be922cddfcf4fe2b39 100644
--- a/api/user.go
+++ b/api/user.go
@@ -36,6 +36,62 @@ func createNewUser(rng *fastRNG.StreamGenerator, cmix, e2e *cyclic.Group) user.U
var cMixKeyBytes, e2eKeyBytes, transmissionSalt, receptionSalt []byte
+ cMixKeyBytes, e2eKeyBytes, transmissionSalt, receptionSalt,
+ transmissionRsaKey, receptionRsaKey = createDhKeys(rng, cmix, e2e)
+
+ // 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 {
+ jww.FATAL.Panicf(err.Error())
+ }
+
+ receptionID, err := xx.NewID(receptionRsaKey.GetPublic(), receptionSalt, id.User)
+ if err != nil {
+ jww.FATAL.Panicf(err.Error())
+ }
+
+ return user.User{
+ TransmissionID: transmissionID.DeepCopy(),
+ TransmissionSalt: transmissionSalt,
+ TransmissionRSA: transmissionRsaKey,
+ ReceptionID: receptionID.DeepCopy(),
+ ReceptionSalt: receptionSalt,
+ ReceptionRSA: receptionRsaKey,
+ Precanned: false,
+ CmixDhPrivateKey: cmix.NewIntFromBytes(cMixKeyBytes),
+ E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes),
+ }
+}
+
+func createDhKeys(rng *fastRNG.StreamGenerator,
+ cmix, e2e *cyclic.Group) (cMixKeyBytes, e2eKeyBytes,
+ transmissionSalt, receptionSalt []byte,
+ transmissionRsaKey, receptionRsaKey *rsa.PrivateKey) {
wg := sync.WaitGroup{}
wg.Add(4)
@@ -93,53 +149,8 @@ func createNewUser(rng *fastRNG.StreamGenerator, cmix, e2e *cyclic.Group) user.U
}()
wg.Wait()
- // 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 {
- jww.FATAL.Panicf(err.Error())
- }
-
- receptionID, err := xx.NewID(receptionRsaKey.GetPublic(), receptionSalt, id.User)
- if err != nil {
- jww.FATAL.Panicf(err.Error())
- }
+ return
- return user.User{
- TransmissionID: transmissionID.DeepCopy(),
- TransmissionSalt: transmissionSalt,
- TransmissionRSA: transmissionRsaKey,
- ReceptionID: receptionID.DeepCopy(),
- ReceptionSalt: receptionSalt,
- ReceptionRSA: receptionRsaKey,
- Precanned: false,
- CmixDhPrivateKey: cmix.NewIntFromBytes(cMixKeyBytes),
- E2eDhPrivateKey: e2e.NewIntFromBytes(e2eKeyBytes),
- }
}
// TODO: Add precanned user code structures here.
diff --git a/interfaces/user/proto.go b/interfaces/user/proto.go
new file mode 100644
index 0000000000000000000000000000000000000000..8eff94714df122bb71a2cee836f4b3a594245dc5
--- /dev/null
+++ b/interfaces/user/proto.go
@@ -0,0 +1,35 @@
+package user
+
+import (
+ "gitlab.com/elixxir/crypto/cyclic"
+ "gitlab.com/xx_network/crypto/signature/rsa"
+ "gitlab.com/xx_network/primitives/id"
+ "time"
+)
+
+type Proto struct {
+ //General Identity
+ TransmissionID *id.ID
+ TransmissionSalt []byte
+ TransmissionRSA *rsa.PrivateKey
+ ReceptionID *id.ID
+ ReceptionSalt []byte
+ ReceptionRSA *rsa.PrivateKey
+ Precanned bool
+ // Timestamp in which user has registered with the network
+ RegistrationTimestamp time.Time
+
+ Username string
+ RegCode string
+
+ TransmissionRegValidationSig []byte
+ ReceptionRegValidationSig []byte
+
+ //cmix Identity
+ CmixDhPrivateKey *cyclic.Int
+ CmixDhPublicKey *cyclic.Int
+
+ //e2e Identity
+ E2eDhPrivateKey *cyclic.Int
+ E2eDhPublicKey *cyclic.Int
+}
diff --git a/interfaces/user/user.go b/interfaces/user/user.go
index 8788856b494cf386dbd903510680935f2b320daa..c3f5875aa6dae91879a063ac83372321f9c0eff3 100644
--- a/interfaces/user/user.go
+++ b/interfaces/user/user.go
@@ -44,3 +44,20 @@ func (u User) GetContact() contact.Contact {
Facts: make([]fact.Fact, 0),
}
}
+
+func NewUserFromProto(proto *Proto) User {
+ return User{
+ TransmissionID: proto.TransmissionID,
+ TransmissionSalt: proto.TransmissionSalt,
+ TransmissionRSA: proto.TransmissionRSA,
+ ReceptionID: proto.ReceptionID,
+ ReceptionSalt: proto.ReceptionSalt,
+ ReceptionRSA: proto.ReceptionRSA,
+ Precanned: proto.Precanned,
+ RegistrationTimestamp: proto.RegistrationTimestamp,
+ CmixDhPrivateKey: proto.CmixDhPrivateKey,
+ CmixDhPublicKey: proto.CmixDhPublicKey,
+ E2eDhPrivateKey: proto.E2eDhPrivateKey,
+ E2eDhPublicKey: proto.E2eDhPublicKey,
+ }
+}
diff --git a/storage/session.go b/storage/session.go
index fd98a85c22e1d1c3aea073ad3d1d9d6a709c6e1c..9b949f240b11f1442c7228ecd695572212574886 100644
--- a/storage/session.go
+++ b/storage/session.go
@@ -101,7 +101,8 @@ func New(baseDir, password string, u userInterface.User, currentVersion version.
"Create new session")
}
- s.user, err = user.NewUser(s.kv, u.TransmissionID, u.ReceptionID, u.TransmissionSalt, u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned)
+ s.user, err = user.NewUser(s.kv, u.TransmissionID, u.ReceptionID, u.TransmissionSalt,
+ u.ReceptionSalt, u.TransmissionRSA, u.ReceptionRSA, u.Precanned)
if err != nil {
return nil, errors.WithMessage(err, "Failed to create user")
}