diff --git a/api/client.go b/api/client.go index 062080589488a01b9b8cd2e7c05521e964b97cae..40bf0ce6bfe6ce2bb6a991591fd53094feb4d1c0 100644 --- a/api/client.go +++ b/api/client.go @@ -81,16 +81,17 @@ func NewClient(ndfJSON, storageDir string, password []byte, registrationCode str 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) - rngStream := rngStreamGen.GetStream() // Parse the NDF def, err := parseNDF(ndfJSON) if err != nil { return err } - cmixGrp, e2eGrp := decodeGroups(def) - protoUser := createNewUser(rngStream, cmixGrp, e2eGrp) + cmixGrp, e2eGrp := decodeGroups(def) + start := time.Now() + protoUser := createNewUser(rngStreamGen, cmixGrp, e2eGrp) + jww.DEBUG.Printf("User generation took: %s", time.Now().Sub(start)) err = checkVersionAndSetupStorage(def, storageDir, password, protoUser, cmixGrp, e2eGrp, rngStreamGen, false, registrationCode) diff --git a/api/user.go b/api/user.go index 48d7f992dfa32b48a3905752c55459ddc710e701..2f807265e708cb037fa0986cecd95aecd7ed798d 100644 --- a/api/user.go +++ b/api/user.go @@ -12,6 +12,7 @@ import ( jww "github.com/spf13/jwalterweatherman" "gitlab.com/elixxir/client/interfaces/user" "gitlab.com/elixxir/crypto/cyclic" + "gitlab.com/elixxir/crypto/fastRNG" "gitlab.com/xx_network/crypto/csprng" "gitlab.com/xx_network/crypto/signature/rsa" "gitlab.com/xx_network/crypto/xx" @@ -29,58 +30,100 @@ const ( ) // createNewUser generates an identity for cMix -func createNewUser(rng csprng.Source, cmix, e2e *cyclic.Group) user.User { +func createNewUser(rng *fastRNG.StreamGenerator, cmix, e2e *cyclic.Group) user.User { // 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()) - } + var transmissionRsaKey, receptionRsaKey *rsa.PrivateKey - // 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()) - } + var cMixKeyBytes, e2eKeyBytes, transmissionSalt, receptionSalt []byte + + wg := sync.WaitGroup{} + + wg.Add(4) + + go func(){ + defer wg.Done() + var err error + // 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. + stream := rng.GetStream() + cMixKeyBytes, err = csprng.GenerateInGroup(cmix.GetPBytes(), 256, stream) + stream.Close() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + }() + + go func(){ + defer wg.Done() + var 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? + stream := rng.GetStream() + e2eKeyBytes, err = csprng.GenerateInGroup(e2e.GetPBytes(), 256, stream) + stream.Close() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + }() // RSA Keygen (4096 bit defaults) - transmissionRsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) + go func() { + defer wg.Done() + var err error + stream := rng.GetStream() + transmissionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen) + stream.Close() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + }() + + go func() { + defer wg.Done() + var err error + stream := rng.GetStream() + receptionRsaKey, err = rsa.GenerateKey(stream, rsa.DefaultRSABitLen) + stream.Close() + if err != nil { + jww.FATAL.Panicf(err.Error()) + } + }() + 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()) } - receptionRsaKey, err := rsa.GenerateKey(rng, rsa.DefaultRSABitLen) - if err != nil { - jww.FATAL.Panicf(err.Error()) + if n != SaltSize { + jww.FATAL.Panicf("transmissionSalt size too small: %d", n) } - // Salt, UID, etc gen - transmissionSalt := make([]byte, SaltSize) - n, err := csprng.NewSystemRNG().Read(transmissionSalt) + 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()) } - // Salt, UID, etc gen - receptionSalt := make([]byte, SaltSize) - n, err = csprng.NewSystemRNG().Read(receptionSalt) - if err != nil { - jww.FATAL.Panicf(err.Error()) - } - if n != SaltSize { - jww.FATAL.Panicf("receptionSalt size too small: %d", n) - } receptionID, err := xx.NewID(receptionRsaKey.GetPublic(), receptionSalt, id.User) if err != nil { jww.FATAL.Panicf(err.Error())