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

Merge branch 'XX-2656/newload-2' into 'peppa/newClient'

Preliminary New and Load Functions

See merge request !420
parents 7a6b4c8a 034dfebf
No related branches found
No related tags found
No related merge requests found
......@@ -14,10 +14,16 @@ import (
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/context"
"gitlab.com/elixxir/client/context/params"
"gitlab.com/elixxir/client/context/stoppable"
"gitlab.com/elixxir/client/context/switchboard"
"gitlab.com/elixxir/client/network"
"gitlab.com/elixxir/client/storage"
pb "gitlab.com/elixxir/comms/mixmessages"
"gitlab.com/elixxir/crypto/csprng"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/fastRNG"
"gitlab.com/elixxir/crypto/large"
"gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/crypto/tls"
"gitlab.com/xx_network/primitives/id"
......@@ -36,32 +42,68 @@ 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(network, storageDir string, password []byte) (*Client, error) {
func NewClient(netJSON, storageDir string, password []byte) (*Client, error) {
if clientStorageExists(storageDir) {
return nil, errors.Errorf("client already exists at %s",
storageDir)
}
// Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
rngStream := rngStreamGen.GetStream()
// Parse the NDF
//ndf, err := parseNDF(network)
//if err != nil {
// return nil, err
//}
ndf, err := parseNDF(netJSON)
if err != nil {
return nil, err
}
cmixGrp, e2eGrp := decodeGroups(ndf)
user := createNewUser(rngStream, cmixGrp, e2eGrp)
// Create Storage
passwordStr := string(password)
storageSess, err := storage.New(storageDir, passwordStr,
user.UID, user.Salt, user.RSAKey, user.IsPrecanned,
user.CMixKey, user.E2EKey, cmixGrp, e2eGrp, rngStreamGen)
if err != nil {
return nil, err
}
// Create network, context, switchboard
// Save NDF to be used in the future
err = storageSess.SetNDF(netJSON)
if err != nil {
return nil, err
}
// Generate Keys
// Set up a new context
ctx := &context.Context{
Session: storageSess,
Switchboard: switchboard.New(),
Rng: rngStreamGen,
Manager: nil,
}
// Register with network
// Initialize network and link it to context
netman, err := network.NewManager(ctx, params.GetDefaultNetwork(), ndf)
if err != nil {
return nil, err
}
ctx.Manager = netman
client := &Client{
storage: nil,
ctx: nil,
switchboard: nil,
network: nil,
storage: storageSess,
ctx: ctx,
switchboard: ctx.Switchboard,
network: netman,
}
// Now register with network, note that regCode is no longer required
err = client.RegisterWithPermissioning("")
if err != nil {
return nil, err
}
return client, nil
}
......@@ -72,16 +114,47 @@ func LoadClient(storageDir string, password []byte) (*Client, error) {
storageDir)
}
// Use fastRNG for RNG ops (AES fortuna based RNG using system RNG)
rngStreamGen := fastRNG.NewStreamGenerator(12, 3, csprng.NewSystemRNG)
// Load Storage
passwordStr := string(password)
storageSess, err := storage.Load(storageDir, passwordStr, rngStreamGen)
if err != nil {
return nil, err
}
// Load and create network, context, switchboard
netJSON, err := storageSess.GetNDF()
if err != nil {
return nil, err
}
ndf, err := parseNDF(string(netJSON))
if err != nil {
return nil, err
}
// Set up a new context
ctx := &context.Context{
Session: storageSess,
Switchboard: switchboard.New(),
Rng: rngStreamGen,
Manager: nil,
}
// Initialize network and link it to context
netman, err := network.NewManager(ctx, params.GetDefaultNetwork(), ndf)
if err != nil {
return nil, err
}
ctx.Manager = netman
client := &Client{
storage: nil,
ctx: nil,
switchboard: nil,
network: nil,
storage: storageSess,
ctx: ctx,
switchboard: ctx.Switchboard,
network: netman,
}
return client, nil
}
......@@ -372,3 +445,19 @@ func parseNDF(ndfString string) (*ndf.NetworkDefinition, error) {
return ndf, nil
}
// decodeGroups returns the e2e and cmix groups from the ndf
func decodeGroups(ndf *ndf.NetworkDefinition) (cmixGrp, e2eGrp *cyclic.Group) {
largeIntBits := 16
//Generate the cmix group
cmixGrp = cyclic.NewGroup(
large.NewIntFromString(ndf.CMIX.Prime, largeIntBits),
large.NewIntFromString(ndf.CMIX.Generator, largeIntBits))
//Generate the e2e group
e2eGrp = cyclic.NewGroup(
large.NewIntFromString(ndf.E2E.Prime, largeIntBits),
large.NewIntFromString(ndf.E2E.Generator, largeIntBits))
return cmixGrp, e2eGrp
}
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2019 Privategrity Corporation /
// /
// All rights reserved. /
////////////////////////////////////////////////////////////////////////////////
package api
import (
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/crypto/csprng"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/xx"
"gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/primitives/id"
)
type user struct {
UID *id.ID
Salt []byte
RSAKey *rsa.PrivateKey
CMixKey *cyclic.Int
E2EKey *cyclic.Int
IsPrecanned bool
}
const (
// SaltSize size of user salts
SaltSize = 32
)
// createNewUser generates an identity for cMix
func createNewUser(rng csprng.Source, cmix, e2e *cyclic.Group) user {
// RSA Keygen (4096 bit defaults)
rsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
// CMIX Keygen
// FIXME: Why 256 bits? -- this is spec but not explained, it has
// to do with optimizing operations on one side and still preserves
// decent security -- cite this.
cMixKeyBytes, err := csprng.GenerateInGroup(cmix.GetPBytes(), 256, rng)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
// DH Keygen
// FIXME: Why 256 bits? -- this is spec but not explained, it has
// to do with optimizing operations on one side and still preserves
// decent security -- cite this. Why valid for BOTH e2e and cmix?
e2eKeyBytes, err := csprng.GenerateInGroup(e2e.GetPBytes(), 256, rng)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
// Salt, UID, etc gen
salt := make([]byte, SaltSize)
n, err := csprng.NewSystemRNG().Read(salt)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
if n != SaltSize {
jww.FATAL.Panicf("salt size too small: %d", n)
}
userID, err := xx.NewID(rsaKey.GetPublic(), salt, id.User)
if err != nil {
jww.FATAL.Panicf(err.Error())
}
return user{
UID: userID,
Salt: salt,
RSAKey: rsaKey,
CMixKey: cmix.NewIntFromBytes(cMixKeyBytes),
E2EKey: e2e.NewIntFromBytes(e2eKeyBytes),
IsPrecanned: false,
}
}
// TODO: Add precanned user code structures here.
......@@ -254,6 +254,7 @@ gitlab.com/xx_network/comms v0.0.0-20200910173932-bd179f5fee4f h1:ExTCqEoro7VuS1
gitlab.com/xx_network/comms v0.0.0-20200910173932-bd179f5fee4f/go.mod h1:+jEkDQKoK51WLl2ZZuxfAZkz6YFbUQ+oZfH0dt2wIF0=
gitlab.com/xx_network/comms v0.0.0-20200915154643-d533291041b7 h1:lPx1wpkjNpwLaZ0pyd7/iCcdITjT+eCMmb0HXCVoIkk=
gitlab.com/xx_network/comms v0.0.0-20200915154643-d533291041b7/go.mod h1:+jEkDQKoK51WLl2ZZuxfAZkz6YFbUQ+oZfH0dt2wIF0=
gitlab.com/xx_network/crypto v0.0.0-20200805231039-4aa0e350ed0a h1:BlfWGPokU6yU69O+PGGsgc5iA/P9gERbHzYUvjoYbgM=
gitlab.com/xx_network/crypto v0.0.0-20200806202113-978fa1984bbf/go.mod h1:i0df/q6dDCBiscgD51fMoS2U2TBrm6LcyN822JmB5Tw=
gitlab.com/xx_network/crypto v0.0.0-20200806235322-ede3c15881ce h1:gypNBUl2guESEv4MDgH+miwYqR4jPoWM8dLt2Zs5gIs=
gitlab.com/xx_network/crypto v0.0.0-20200806235322-ede3c15881ce/go.mod h1:i0df/q6dDCBiscgD51fMoS2U2TBrm6LcyN822JmB5Tw=
......
......@@ -19,14 +19,15 @@ import (
"gitlab.com/elixxir/client/storage/utility"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/crypto/large"
"gitlab.com/elixxir/crypto/fastRNG"
"gitlab.com/elixxir/crypto/large"
"gitlab.com/elixxir/ekv"
"gitlab.com/xx_network/crypto/signature/rsa"
"gitlab.com/xx_network/primitives/id"
"gitlab.com/xx_network/primitives/ndf"
"sync"
"testing"
"time"
)
// Number of rounds to store in the CheckedRound buffer
......@@ -216,6 +217,25 @@ func (s *Session) Partition() *partition.Store {
return s.partition
}
// SetNDF stores a network definition json file
func (s *Session) SetNDF(ndfJSON string) error {
return s.Set("NetworkDefinition",
&versioned.Object{
Version: uint64(1),
Data: []byte(ndfJSON),
Timestamp: time.Now(),
})
}
// Returns the stored network definition json file
func (s *Session) GetNDF() (string, error) {
ndf, err := s.Get("NetworkDefinition")
if err != nil {
return "", err
}
return string(ndf.Data), nil
}
// Get an object from the session
func (s *Session) Get(key string) (*versioned.Object, error) {
return s.kv.Get(key)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment