diff --git a/storage/password.go b/storage/password.go index 7be49b310b54b7aa2764678f35d0b91550d2c491..5dec9055907b819c3290be05cd07454ddd312036 100644 --- a/storage/password.go +++ b/storage/password.go @@ -23,6 +23,7 @@ import ( "github.com/pkg/errors" jww "github.com/spf13/jwalterweatherman" + "gitlab.com/elixxir/crypto/hash" "gitlab.com/elixxir/wasm-utils/exception" "gitlab.com/elixxir/wasm-utils/storage" "gitlab.com/elixxir/wasm-utils/utils" @@ -40,6 +41,8 @@ const ( // saltLen is the length of the salt. Recommended to be 16 bytes here: // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-argon2-04#section-3.1 saltLen = 16 + + internalPasswordConstant = "XXInternalPassword" ) // Storage keys. @@ -58,7 +61,7 @@ const ( // Error messages. const ( // initInternalPassword - readInternalPasswordErr = "could not generate internal password: %+v" + readInternalPasswordErr = "could not generate" internalPasswordNumBytesErr = "expected %d bytes for internal password, found %d bytes" // getInternalPassword @@ -153,6 +156,9 @@ func getOrInit(externalPassword string) ([]byte, error) { // changeExternalPassword is the private function for ChangeExternalPassword // that is used for testing. func changeExternalPassword(oldExternalPassword, newExternalPassword string) error { + // NOTE: the following no longer works in synchronized environments, so + // disabled in produciton. + jww.FATAL.Panicf("cannot change password, unimplemented") localStorage := storage.GetLocalStorage() internalPassword, err := getInternalPassword( oldExternalPassword, localStorage) @@ -193,14 +199,22 @@ func initInternalPassword(externalPassword string, params argonParams) ([]byte, error) { internalPassword := make([]byte, internalPasswordLen) + // FIXME: The internal password is now just an expansion of + // the users password text. We couldn't preserve the following + // when doing cross-device sync. + h := hash.CMixHash.New() + h.Write([]byte(externalPassword)) + h.Write(internalPassword) + copy(internalPassword, h.Sum(nil)[:internalPasswordLen]) + // Generate internal password - n, err := csprng.Read(internalPassword) - if err != nil { - return nil, errors.Errorf(readInternalPasswordErr, err) - } else if n != internalPasswordLen { - return nil, errors.Errorf( - internalPasswordNumBytesErr, internalPasswordLen, n) - } + // n, err := csprng.Read(internalPassword) + // if err != nil { + // return nil, errors.Errorf(readInternalPasswordErr, err) + // } else if n != internalPasswordLen { + // return nil, errors.Errorf( + // internalPasswordNumBytesErr, internalPasswordLen, n) + // } // Generate and store salt salt, err := makeSalt(csprng) diff --git a/storage/password_test.go b/storage/password_test.go index 0e4c4c64105e93247cf24d1665360fdbd834a687..fecd785c51c7e919ab511e2d8d5821dd6f4b37f5 100644 --- a/storage/password_test.go +++ b/storage/password_test.go @@ -44,37 +44,37 @@ func Test_getOrInit(t *testing.T) { // Tests that changeExternalPassword correctly changes the password and updates // the encryption. -func Test_changeExternalPassword(t *testing.T) { - oldExternalPassword := "myPassword" - newExternalPassword := "hunter2" - oldInternalPassword, err := getOrInit(oldExternalPassword) - if err != nil { - t.Errorf("%+v", err) - } - - err = changeExternalPassword(oldExternalPassword, newExternalPassword) - if err != nil { - t.Errorf("%+v", err) - } - - newInternalPassword, err := getOrInit(newExternalPassword) - if err != nil { - t.Errorf("%+v", err) - } - - if !bytes.Equal(oldInternalPassword, newInternalPassword) { - t.Errorf("Internal password was not changed in storage. Old and new "+ - "should be different.\nold: %+v\nnew: %+v", - oldInternalPassword, newInternalPassword) - } - - _, err = getOrInit(oldExternalPassword) - expectedErr := strings.Split(decryptWithPasswordErr, "%")[0] - if err == nil || !strings.Contains(err.Error(), expectedErr) { - t.Errorf("Unexpected error when trying to get internal password with "+ - "old external password.\nexpected: %s\nreceived: %+v", expectedErr, err) - } -} +// func Test_changeExternalPassword(t *testing.T) { +// oldExternalPassword := "myPassword" +// newExternalPassword := "hunter2" +// oldInternalPassword, err := getOrInit(oldExternalPassword) +// if err != nil { +// t.Errorf("%+v", err) +// } + +// err = changeExternalPassword(oldExternalPassword, newExternalPassword) +// if err != nil { +// t.Errorf("%+v", err) +// } + +// newInternalPassword, err := getOrInit(newExternalPassword) +// if err != nil { +// t.Errorf("%+v", err) +// } + +// if !bytes.Equal(oldInternalPassword, newInternalPassword) { +// t.Errorf("Internal password was not changed in storage. Old and new "+ +// "should be different.\nold: %+v\nnew: %+v", +// oldInternalPassword, newInternalPassword) +// } + +// _, err = getOrInit(oldExternalPassword) +// expectedErr := strings.Split(decryptWithPasswordErr, "%")[0] +// if err == nil || !strings.Contains(err.Error(), expectedErr) { +// t.Errorf("Unexpected error when trying to get internal password with "+ +// "old external password.\nexpected: %s\nreceived: %+v", expectedErr, err) +// } +// } // Tests that verifyPassword returns true for a valid password and false for an // invalid password @@ -154,20 +154,20 @@ func Test_initInternalPassword_CsprngReadError(t *testing.T) { // Tests that initInternalPassword returns an error when the RNG does not // return enough bytes. -func Test_initInternalPassword_CsprngReadNumBytesError(t *testing.T) { - externalPassword := "myPassword" - ls := storage.GetLocalStorage() - b := bytes.NewBuffer(make([]byte, internalPasswordLen/2)) - - expectedErr := fmt.Sprintf( - internalPasswordNumBytesErr, internalPasswordLen, internalPasswordLen/2) - - _, err := initInternalPassword(externalPassword, ls, b, defaultParams()) - if err == nil || !strings.Contains(err.Error(), expectedErr) { - t.Errorf("Unexpected error when RNG does not return enough bytes."+ - "\nexpected: %s\nreceived: %+v", expectedErr, err) - } -} +// func Test_initInternalPassword_CsprngReadNumBytesError(t *testing.T) { +// externalPassword := "myPassword" +// ls := storage.GetLocalStorage() +// b := bytes.NewBuffer(make([]byte, internalPasswordLen/2)) + +// expectedErr := fmt.Sprintf( +// internalPasswordNumBytesErr, internalPasswordLen, internalPasswordLen/2) + +// _, err := initInternalPassword(externalPassword, ls, b, defaultParams()) +// if err == nil || !strings.Contains(err.Error(), expectedErr) { +// t.Errorf("Unexpected error when RNG does not return enough bytes."+ +// "\nexpected: %s\nreceived: %+v", expectedErr, err) +// } +// } // Tests that getInternalPassword returns the internal password that is saved // to local storage by initInternalPassword. diff --git a/wasm/collective.go b/wasm/collective.go index 5bd0fa145fd214752475bc1eaa9601dc881297e5..5c2eb771502e3206210cfc0dca78b3743f7b3fc0 100644 --- a/wasm/collective.go +++ b/wasm/collective.go @@ -516,13 +516,12 @@ func (rsCB *RemoteStore) Write(path string, data []byte) error { // Returns: // - JSON of [bindings.RemoteStoreReport] (Uint8Array). // - Catches any thrown errors (of type Error) and returns it as an error. -func (rsCB *RemoteStore) GetLastModified(path string) ([]byte, error) { - fn := func() js.Value { return rsCB.getLastModified(path) } - v, err := exception.RunAndCatch(fn) +func (rsCB *RemoteStore) GetLastModified(path string) (string, error) { + v, err := utils.Await(rsCB.getLastModified(path)) if err != nil { - return nil, err + return "", js.Error{Value: err[0]} } - return utils.CopyBytesToGo(v), err + return v[0].String(), nil } // GetLastWrite implements [bindings.RemoteStore.GetLastWrite() @@ -530,13 +529,12 @@ func (rsCB *RemoteStore) GetLastModified(path string) ([]byte, error) { // Returns: // - JSON of [bindings.RemoteStoreReport] (Uint8Array). // - Catches any thrown errors (of type Error) and returns it as an error. -func (rsCB *RemoteStore) GetLastWrite() ([]byte, error) { - fn := func() js.Value { return rsCB.getLastWrite() } - v, err := exception.RunAndCatch(fn) +func (rsCB *RemoteStore) GetLastWrite() (string, error) { + v, err := utils.Await(rsCB.getLastWrite()) if err != nil { - return nil, err + return "", js.Error{Value: err[0]} } - return utils.CopyBytesToGo(v), err + return v[0].String(), nil } // ReadDir implements [bindings.RemoteStore.ReadDir]