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())