github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/engine/passphrase_change_test.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package engine
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/keybase/client/go/libkb"
    11  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func withNewProvisionalLoginForFakeUser(m libkb.MetaContext, u *FakeUser) libkb.MetaContext {
    16  	m = m.WithNewProvisionalLoginContextForUserVersionAndUsername(u.UserVersion(), libkb.NewNormalizedUsername(u.Username))
    17  	return m
    18  }
    19  
    20  func tryPassphrase(tc libkb.TestContext, u *FakeUser, pp string) error {
    21  	m := NewMetaContextForTest(tc)
    22  	m = withNewProvisionalLoginForFakeUser(m, u)
    23  	_, err := libkb.VerifyPassphraseGetStreamInLoginContext(m, pp)
    24  	return err
    25  }
    26  
    27  func verifyPassphraseChange(tc libkb.TestContext, u *FakeUser, newPassphrase string) {
    28  	err := tryPassphrase(tc, u, newPassphrase)
    29  	require.NoError(tc.T, err, "verified new passphrase works")
    30  	err = tryPassphrase(tc, u, u.Passphrase)
    31  	require.Error(tc.T, err, "verified old passphrase fails")
    32  	if testing.Verbose() {
    33  		fmt.Printf("browser test -- username:  %s    password:  %s\n", u.Username, newPassphrase)
    34  	}
    35  }
    36  
    37  func assertLoadSecretKeys(tc libkb.TestContext, u *FakeUser, msg string) {
    38  	tc.G.Log.Debug("In assertLoadSecretKeys")
    39  
    40  	me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G))
    41  	if err != nil {
    42  		tc.T.Fatalf("%s: %s", msg, err)
    43  	}
    44  	if me == nil {
    45  		tc.T.Fatalf("%s: nil LoadMe result", msg)
    46  	}
    47  	skarg := libkb.SecretKeyArg{
    48  		Me:      me,
    49  		KeyType: libkb.DeviceSigningKeyType,
    50  	}
    51  	parg := libkb.SecretKeyPromptArg{
    52  		Ska:      skarg,
    53  		SecretUI: u.NewSecretUI(),
    54  		Reason:   "testing sig",
    55  	}
    56  	m := NewMetaContextForTest(tc)
    57  	m = withNewProvisionalLoginForFakeUser(m, u)
    58  
    59  	tc.G.Log.Debug("doing a silent passphrase login for session token")
    60  	err = libkb.PassphraseLoginNoPrompt(m, u.Username, u.Passphrase)
    61  	require.NoError(tc.T, err)
    62  
    63  	tc.G.Log.Debug("Calling GetSecretKeyWithPrompt (for signing)")
    64  	sigKey, err := tc.G.Keyrings.GetSecretKeyWithPrompt(m, parg)
    65  	if err != nil {
    66  		tc.T.Fatalf("%s: %s", msg, err)
    67  	}
    68  	if sigKey == nil {
    69  		tc.T.Fatalf("%s: got nil signing key", msg)
    70  	}
    71  
    72  	parg.Ska.KeyType = libkb.DeviceEncryptionKeyType
    73  	tc.G.Log.Debug("Calling GetSecretKeyWithPrompt (for encryption)")
    74  	encKey, err := tc.G.Keyrings.GetSecretKeyWithPrompt(m, parg)
    75  	if err != nil {
    76  		tc.T.Fatalf("%s: %s", msg, err)
    77  	}
    78  	if encKey == nil {
    79  		tc.T.Fatalf("%s: got nil encryption key", msg)
    80  	}
    81  }
    82  
    83  func assertLoadPGPKeys(tc libkb.TestContext, u *FakeUser) {
    84  	me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G))
    85  	if err != nil {
    86  		tc.T.Fatal(err)
    87  	}
    88  
    89  	ska := libkb.SecretKeyArg{
    90  		Me:      me,
    91  		KeyType: libkb.PGPKeyType,
    92  	}
    93  	parg := libkb.SecretKeyPromptArg{
    94  		Ska:      ska,
    95  		SecretUI: u.NewSecretUI(),
    96  		Reason:   "pgp test",
    97  	}
    98  	m := NewMetaContextForTest(tc)
    99  	key, err := tc.G.Keyrings.GetSecretKeyWithPrompt(m, parg)
   100  	if err != nil {
   101  		tc.T.Fatal(err)
   102  	}
   103  
   104  	var ok bool
   105  	_, ok = key.(*libkb.PGPKeyBundle)
   106  	if !ok {
   107  		tc.T.Errorf("key type: %T, expected libkb.PGPKeyBundle", key)
   108  	}
   109  }
   110  
   111  // Test changing the passphrase when user knows current
   112  // passphrase.
   113  func TestPassphraseChangeKnown(t *testing.T) {
   114  	tc := SetupEngineTest(t, "PassphraseChange")
   115  	defer tc.Cleanup()
   116  
   117  	u := CreateAndSignupFakeUser(tc, "login")
   118  	newPassphrase := "password1234"
   119  	arg := &keybase1.PassphraseChangeArg{
   120  		OldPassphrase: u.Passphrase,
   121  		Passphrase:    newPassphrase,
   122  	}
   123  
   124  	// using an empty secret ui to make sure existing pp doesn't come from ui prompt:
   125  	uis := libkb.UIs{
   126  		SecretUI: &libkb.TestSecretUI{},
   127  	}
   128  	eng := NewPassphraseChange(tc.G, arg)
   129  	m := NewMetaContextForTest(tc).WithUIs(uis)
   130  	if err := RunEngine2(m, eng); err != nil {
   131  		t.Fatal(err)
   132  	}
   133  
   134  	verifyPassphraseChange(tc, u, newPassphrase)
   135  
   136  	u.Passphrase = newPassphrase
   137  	assertLoadSecretKeys(tc, u, "passphrase change known")
   138  }
   139  
   140  // Test error when trying to change passphrase to shorter than 6
   141  // chars long.
   142  func TestPassphraseChangeShort(t *testing.T) {
   143  	tc := SetupEngineTest(t, "PassphraseChange")
   144  	defer tc.Cleanup()
   145  
   146  	u := CreateAndSignupFakeUser(tc, "login")
   147  	newPassphrase := "pass"
   148  	arg := &keybase1.PassphraseChangeArg{
   149  		OldPassphrase: u.Passphrase,
   150  		Passphrase:    newPassphrase,
   151  	}
   152  	uis := libkb.UIs{
   153  		SecretUI: &libkb.TestSecretUI{},
   154  	}
   155  	eng := NewPassphraseChange(tc.G, arg)
   156  	m := NewMetaContextForTest(tc).WithUIs(uis)
   157  	err := RunEngine2(m, eng)
   158  	if err == nil {
   159  		t.Fatal("expected error with new short passphrase")
   160  	}
   161  	if _, ok := err.(libkb.PassphraseError); !ok {
   162  		t.Fatalf("expected libkb.PassphraseError, got %T", err)
   163  	}
   164  }
   165  
   166  // Test changing the passphrase when user knows current
   167  // passphrase, prompt for it.
   168  func TestPassphraseChangeKnownPrompt(t *testing.T) {
   169  	tc := SetupEngineTest(t, "PassphraseChange")
   170  	defer tc.Cleanup()
   171  
   172  	u := CreateAndSignupFakeUser(tc, "login")
   173  
   174  	// clear the passphrase stream cache to force a prompt
   175  	// for the existing passphrase.
   176  	clearCaches(tc.G)
   177  
   178  	// Test changing passphrase 3 times; so that old passphrase
   179  	// cache is properly busted.
   180  	newPassphrase := "password1234"
   181  	numChanges := 3
   182  	for i := 0; i < numChanges; i++ {
   183  
   184  		arg := &keybase1.PassphraseChangeArg{
   185  			Passphrase: newPassphrase,
   186  		}
   187  		secui := u.NewSecretUI()
   188  		uis := libkb.UIs{
   189  			SecretUI: secui,
   190  		}
   191  		eng := NewPassphraseChange(tc.G, arg)
   192  		m := NewMetaContextForTest(tc).WithUIs(uis)
   193  		if err := RunEngine2(m, eng); err != nil {
   194  			t.Fatal(err)
   195  		}
   196  
   197  		// We only call this the last time through, since internally,
   198  		// verifyPassphraseChange calls ClearStreamCache(), which is
   199  		// the bug fix that we're actually trying to test by doing multiple
   200  		// passphrase changes.
   201  		if i == numChanges-1 {
   202  			verifyPassphraseChange(tc, u, newPassphrase)
   203  		}
   204  
   205  		if !secui.CalledGetPassphrase {
   206  			t.Errorf("get passphrase not called")
   207  		}
   208  
   209  		u.Passphrase = newPassphrase
   210  		assertLoadSecretKeys(tc, u, "passphrase change known prompt")
   211  		newPassphrase += "-xo"
   212  	}
   213  }
   214  
   215  // Test changing the passphrase when user knows current
   216  // passphrase, prompt for it.
   217  func TestPassphraseChangeKnownPromptRepeatOld(t *testing.T) {
   218  	tc := SetupEngineTest(t, "PassphraseChange")
   219  	defer tc.Cleanup()
   220  
   221  	u := CreateAndSignupFakeUser(tc, "login")
   222  	m := NewMetaContextForTest(tc)
   223  
   224  	// clear the passphrase stream cache to force a prompt
   225  	// for the existing passphrase.
   226  	m.ActiveDevice().ClearCaches()
   227  
   228  	// Test changing passphrase 3 times; so that old passphrase
   229  	// cache is properly busted.
   230  	newPassphrase := "password1234"
   231  	numChanges := 3
   232  	for i := 0; i < numChanges; i++ {
   233  
   234  		arg := &keybase1.PassphraseChangeArg{
   235  			Passphrase: newPassphrase,
   236  		}
   237  		secui := u.NewSecretUI()
   238  		uis := libkb.UIs{
   239  			SecretUI: secui,
   240  		}
   241  		eng := NewPassphraseChange(tc.G, arg)
   242  		m = m.WithUIs(uis)
   243  		if err := RunEngine2(m, eng); err != nil {
   244  			t.Fatal(err)
   245  		}
   246  
   247  		// We only call this the last time through, since internally,
   248  		// verifyPassphraseChange calls ClearStreamCache(), which is
   249  		// the bug fix that we're actually trying to test by doing multiple
   250  		// passphrase changes.
   251  		if i == numChanges-1 {
   252  			m := NewMetaContextForTest(tc)
   253  			_, err := libkb.VerifyPassphraseForLoggedInUser(m, newPassphrase)
   254  			if err != nil {
   255  				t.Fatal(err)
   256  			}
   257  		}
   258  
   259  		if !secui.CalledGetPassphrase {
   260  			t.Errorf("get passphrase not called")
   261  		}
   262  
   263  		u.Passphrase = newPassphrase
   264  		assertLoadSecretKeys(tc, u, "passphrase change known prompt")
   265  	}
   266  }
   267  
   268  // Test changing the passphrase after logging in via pubkey.
   269  func TestPassphraseChangeAfterPubkeyLogin(t *testing.T) {
   270  	tc := SetupEngineTest(t, "PassphraseChange")
   271  	defer tc.Cleanup()
   272  
   273  	u := CreateAndSignupFakeUser(tc, "login")
   274  
   275  	// this should do a pubkey login
   276  	Logout(tc)
   277  
   278  	secui := u.NewSecretUI()
   279  	if err := u.LoginWithSecretUI(secui, tc.G); err != nil {
   280  		t.Fatal(err)
   281  	}
   282  	if !secui.CalledGetPassphrase {
   283  		t.Errorf("get keybase passphrase not called")
   284  	}
   285  
   286  	newPassphrase := "password1234"
   287  	arg := &keybase1.PassphraseChangeArg{
   288  		Passphrase: newPassphrase,
   289  	}
   290  	uis := libkb.UIs{
   291  		SecretUI: secui,
   292  	}
   293  	eng := NewPassphraseChange(tc.G, arg)
   294  	m := NewMetaContextForTest(tc).WithUIs(uis)
   295  	if err := RunEngine2(m, eng); err != nil {
   296  		t.Fatal(err)
   297  	}
   298  
   299  	verifyPassphraseChange(tc, u, newPassphrase)
   300  
   301  	u.Passphrase = newPassphrase
   302  	assertLoadSecretKeys(tc, u, "passphrase change after pubkey login")
   303  }
   304  
   305  // Test changing the passphrase when previous pp stream available.
   306  func TestPassphraseChangeKnownNotSupplied(t *testing.T) {
   307  	tc := SetupEngineTest(t, "PassphraseChange")
   308  	defer tc.Cleanup()
   309  
   310  	u := CreateAndSignupFakeUser(tc, "login")
   311  	newPassphrase := "password1234"
   312  	arg := &keybase1.PassphraseChangeArg{
   313  		Passphrase: newPassphrase,
   314  	}
   315  	secui := &libkb.TestSecretUI{}
   316  	uis := libkb.UIs{
   317  		SecretUI: secui,
   318  	}
   319  	eng := NewPassphraseChange(tc.G, arg)
   320  	m := NewMetaContextForTest(tc).WithUIs(uis)
   321  	if err := RunEngine2(m, eng); err != nil {
   322  		t.Fatal(err)
   323  	}
   324  
   325  	verifyPassphraseChange(tc, u, newPassphrase)
   326  
   327  	if secui.CalledGetPassphrase {
   328  		t.Errorf("get kb passphrase called")
   329  	}
   330  
   331  	u.Passphrase = newPassphrase
   332  	assertLoadSecretKeys(tc, u, "passphrase change known, not supplied")
   333  }
   334  
   335  // Test changing the passphrase when user forgets current
   336  // passphrase.
   337  func TestPassphraseChangeUnknown(t *testing.T) {
   338  	tc := SetupEngineTest(t, "PassphraseChange")
   339  	defer tc.Cleanup()
   340  
   341  	u := CreateAndSignupFakeUser(tc, "login")
   342  
   343  	// this has a flaw:  the passphrase stream cache is available.
   344  	// it is being used to unlock the secret key to generate the
   345  	// change passphrase proof.
   346  	//
   347  
   348  	newPassphrase := "password1234"
   349  	arg := &keybase1.PassphraseChangeArg{
   350  		Passphrase: newPassphrase,
   351  		Force:      true,
   352  	}
   353  	uis := libkb.UIs{
   354  		SecretUI: &libkb.TestSecretUI{},
   355  	}
   356  	eng := NewPassphraseChange(tc.G, arg)
   357  	m := NewMetaContextForTest(tc).WithUIs(uis)
   358  	if err := RunEngine2(m, eng); err != nil {
   359  		t.Fatal(err)
   360  	}
   361  
   362  	verifyPassphraseChange(tc, u, newPassphrase)
   363  
   364  	u.Passphrase = newPassphrase
   365  	assertLoadSecretKeys(tc, u, "passphrase change unknown")
   366  }
   367  
   368  // Test changing the passphrase when user forgets current
   369  // passphrase and there's no passphrase stream cache.
   370  // No backup key available.
   371  func TestPassphraseChangeUnknownNoPSCache(t *testing.T) {
   372  	tc := SetupEngineTest(t, "PassphraseChange")
   373  	defer tc.Cleanup()
   374  
   375  	f := func(arg *SignupEngineRunArg) {
   376  		arg.SkipPaper = true
   377  	}
   378  
   379  	u, _, _ := CreateAndSignupFakeUserCustomArg(tc, "paper", f)
   380  
   381  	tc.SimulateServiceRestart()
   382  
   383  	newPassphrase := "password1234"
   384  	arg := &keybase1.PassphraseChangeArg{
   385  		Passphrase: newPassphrase,
   386  		Force:      true,
   387  	}
   388  	uis := libkb.UIs{
   389  		SecretUI: &libkb.TestSecretUI{},
   390  	}
   391  	eng := NewPassphraseChange(tc.G, arg)
   392  	m := NewMetaContextForTest(tc).WithUIs(uis)
   393  	err := RunEngine2(m, eng)
   394  	if err == nil {
   395  		t.Fatal("passphrase change should have failed")
   396  	}
   397  	if _, ok := err.(libkb.NoPaperKeysError); !ok {
   398  		t.Fatalf("unexpected error: %s (%T)", err, err)
   399  	}
   400  
   401  	assertLoadSecretKeys(tc, u, "passphrase change unknown, no ps cache")
   402  }
   403  
   404  // Test changing the passphrase when user forgets current
   405  // passphrase and there's no passphrase stream cache.
   406  // Backup key exists
   407  func TestPassphraseChangeUnknownBackupKey(t *testing.T) {
   408  	tc := SetupEngineTest(t, "PassphraseChange")
   409  	defer tc.Cleanup()
   410  
   411  	u := CreateAndSignupFakeUser(tc, "login")
   412  
   413  	uis := libkb.UIs{
   414  		LogUI:    tc.G.UI.GetLogUI(),
   415  		LoginUI:  &libkb.TestLoginUI{},
   416  		SecretUI: &libkb.TestSecretUI{},
   417  	}
   418  	beng := NewPaperKey(tc.G)
   419  	m := NewMetaContextForTest(tc).WithUIs(uis)
   420  	if err := RunEngine2(m, beng); err != nil {
   421  		t.Fatal(err)
   422  	}
   423  	backupPassphrase := beng.Passphrase()
   424  	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
   425  
   426  	m.ActiveDevice().ClearCaches()
   427  
   428  	newPassphrase := "password1234"
   429  	arg := &keybase1.PassphraseChangeArg{
   430  		Passphrase: newPassphrase,
   431  		Force:      true,
   432  	}
   433  	eng := NewPassphraseChange(tc.G, arg)
   434  	if err := RunEngine2(m, eng); err != nil {
   435  		t.Fatal(err)
   436  	}
   437  
   438  	verifyPassphraseChange(tc, u, newPassphrase)
   439  
   440  	u.Passphrase = newPassphrase
   441  	assertLoadSecretKeys(tc, u, "passphrase change unknown, backup key")
   442  }
   443  
   444  // Test changing the passphrase when user forgets current
   445  // passphrase and is logged out, but has a backup key.
   446  func TestPassphraseChangeLoggedOutBackupKey(t *testing.T) {
   447  	tc := SetupEngineTest(t, "PassphraseChange")
   448  	defer tc.Cleanup()
   449  
   450  	u := CreateAndSignupFakeUser(tc, "login")
   451  
   452  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
   453  
   454  	uis := libkb.UIs{
   455  		LogUI:    tc.G.UI.GetLogUI(),
   456  		LoginUI:  &libkb.TestLoginUI{},
   457  		SecretUI: &libkb.TestSecretUI{},
   458  	}
   459  	beng := NewPaperKey(tc.G)
   460  	m := NewMetaContextForTest(tc).WithUIs(uis)
   461  	if err := RunEngine2(m, beng); err != nil {
   462  		t.Fatal(err)
   463  	}
   464  	backupPassphrase := beng.Passphrase()
   465  	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
   466  
   467  	Logout(tc)
   468  
   469  	newPassphrase := "password1234"
   470  	arg := &keybase1.PassphraseChangeArg{
   471  		Passphrase: newPassphrase,
   472  		Force:      true,
   473  	}
   474  	eng := NewPassphraseChange(tc.G, arg)
   475  	if err := RunEngine2(m, eng); err != nil {
   476  		t.Fatal(err)
   477  	}
   478  
   479  	verifyPassphraseChange(tc, u, newPassphrase)
   480  
   481  	u.Passphrase = newPassphrase
   482  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
   483  }
   484  
   485  // Test changing the passphrase when user forgets current passphrase
   486  // and is logged out, but has a backup key (generated by a secret from
   487  // the secret store).
   488  func TestPassphraseChangeLoggedOutBackupKeySecretStore(t *testing.T) {
   489  
   490  	tc := SetupEngineTest(t, "PassphraseChange")
   491  	defer tc.Cleanup()
   492  
   493  	u := NewFakeUserOrBust(tc.T, "login")
   494  	signupArg := MakeTestSignupEngineRunArg(u)
   495  	signupArg.StoreSecret = true
   496  	_ = SignupFakeUserWithArg(tc, u, signupArg)
   497  
   498  	// This needs to happen *before* resetting the login state, as
   499  	// this call will cause the login state to be reloaded.
   500  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
   501  
   502  	tc.SimulateServiceRestart()
   503  
   504  	secretUI := libkb.TestSecretUI{}
   505  	uis := libkb.UIs{
   506  		LogUI:    tc.G.UI.GetLogUI(),
   507  		LoginUI:  &libkb.TestLoginUI{},
   508  		SecretUI: &secretUI,
   509  	}
   510  	beng := NewPaperKey(tc.G)
   511  	m := NewMetaContextForTest(tc).WithUIs(uis)
   512  	if err := RunEngine2(m, beng); err != nil {
   513  		t.Fatal(err)
   514  	}
   515  
   516  	if secretUI.CalledGetPassphrase {
   517  		t.Fatal("GetPassphrase() unexpectedly called")
   518  	}
   519  
   520  	backupPassphrase := beng.Passphrase()
   521  	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
   522  
   523  	Logout(tc)
   524  
   525  	newPassphrase := "password1234"
   526  	arg := &keybase1.PassphraseChangeArg{
   527  		Passphrase: newPassphrase,
   528  		Force:      true,
   529  	}
   530  	eng := NewPassphraseChange(tc.G, arg)
   531  	if err := RunEngine2(m, eng); err != nil {
   532  		t.Fatal(err)
   533  	}
   534  
   535  	verifyPassphraseChange(tc, u, newPassphrase)
   536  
   537  	u.Passphrase = newPassphrase
   538  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
   539  }
   540  
   541  // Test using an lksec-encrypted pgp private key after changing the
   542  // passphrase.
   543  func TestPassphraseChangePGPUsage(t *testing.T) {
   544  	tc := SetupEngineTest(t, "PassphraseChange")
   545  	defer tc.Cleanup()
   546  
   547  	u := createFakeUserWithPGPSibkey(tc)
   548  
   549  	// clear the passphrase stream cache to force a prompt
   550  	// for the existing passphrase.
   551  	clearCaches(tc.G)
   552  
   553  	newPassphrase := "password1234"
   554  	arg := &keybase1.PassphraseChangeArg{
   555  		Passphrase: newPassphrase,
   556  	}
   557  	secui := u.NewSecretUI()
   558  	uis := libkb.UIs{
   559  		SecretUI: secui,
   560  	}
   561  	eng := NewPassphraseChange(tc.G, arg)
   562  	m := NewMetaContextForTest(tc).WithUIs(uis)
   563  	if err := RunEngine2(m, eng); err != nil {
   564  		t.Fatal(err)
   565  	}
   566  
   567  	verifyPassphraseChange(tc, u, newPassphrase)
   568  
   569  	if !secui.CalledGetPassphrase {
   570  		t.Errorf("get kb passphrase not called")
   571  	}
   572  
   573  	u.Passphrase = newPassphrase
   574  	assertLoadSecretKeys(tc, u, "passphrase change pgp")
   575  	assertLoadPGPKeys(tc, u)
   576  }
   577  
   578  // Test using a 3sec-encrypted pgp private key after changing the
   579  // passphrase.
   580  func TestPassphraseChangePGP3Sec(t *testing.T) {
   581  	tc := SetupEngineTest(t, "PassphraseChange")
   582  	defer tc.Cleanup()
   583  
   584  	u := createFakeUserWithPGPSibkeyPushed(tc)
   585  
   586  	// clear the passphrase stream cache to force a prompt
   587  	// for the existing passphrase.
   588  	clearCaches(tc.G)
   589  
   590  	newPassphrase := "password1234"
   591  	arg := &keybase1.PassphraseChangeArg{
   592  		Passphrase: newPassphrase,
   593  	}
   594  	secui := u.NewSecretUI()
   595  	uis := libkb.UIs{
   596  		SecretUI: secui,
   597  	}
   598  	eng := NewPassphraseChange(tc.G, arg)
   599  	m := NewMetaContextForTest(tc).WithUIs(uis)
   600  	if err := RunEngine2(m, eng); err != nil {
   601  		t.Fatal(err)
   602  	}
   603  
   604  	verifyPassphraseChange(tc, u, newPassphrase)
   605  
   606  	if !secui.CalledGetPassphrase {
   607  		t.Errorf("get kb passphrase not called")
   608  	}
   609  
   610  	u.Passphrase = newPassphrase
   611  	assertLoadSecretKeys(tc, u, "passphrase change pgp")
   612  	assertLoadPGPKeys(tc, u)
   613  }
   614  
   615  // Test changing the passphrase when user forgets current
   616  // passphrase and is logged out, but has a backup key.
   617  // Also, this user has a 3sec-encrypted private pgp key
   618  // that will be unusable after changing passphrase.
   619  func TestPassphraseChangeLoggedOutBackupKeyPlusPGP(t *testing.T) {
   620  	tc := SetupEngineTest(t, "PassphraseChange")
   621  	defer tc.Cleanup()
   622  
   623  	u := createFakeUserWithPGPSibkeyPushed(tc)
   624  
   625  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
   626  
   627  	uis := libkb.UIs{
   628  		LogUI:    tc.G.UI.GetLogUI(),
   629  		LoginUI:  &libkb.TestLoginUI{},
   630  		SecretUI: &libkb.TestSecretUI{},
   631  	}
   632  	beng := NewPaperKey(tc.G)
   633  	m := NewMetaContextForTest(tc).WithUIs(uis)
   634  	if err := RunEngine2(m, beng); err != nil {
   635  		t.Fatal(err)
   636  	}
   637  	backupPassphrase := beng.Passphrase()
   638  	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
   639  	Logout(tc)
   640  
   641  	newPassphrase := "password1234"
   642  	arg := &keybase1.PassphraseChangeArg{
   643  		Passphrase: newPassphrase,
   644  		Force:      true,
   645  	}
   646  	eng := NewPassphraseChange(tc.G, arg)
   647  	if err := RunEngine2(m, eng); err != nil {
   648  		t.Fatal(err)
   649  	}
   650  
   651  	verifyPassphraseChange(tc, u, newPassphrase)
   652  
   653  	u.Passphrase = newPassphrase
   654  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
   655  }
   656  
   657  // Test changing the passphrase when user forgets current passphrase
   658  // and is logged out, but has a backup key (generated by a secret from
   659  // the secret store).  And test using an lksec pgp key after the change.
   660  func TestPassphraseChangeLoggedOutBackupKeySecretStorePGP(t *testing.T) {
   661  
   662  	tc := SetupEngineTest(t, "PassphraseChange")
   663  	defer tc.Cleanup()
   664  
   665  	u := NewFakeUserOrBust(tc.T, "login")
   666  	signupArg := MakeTestSignupEngineRunArg(u)
   667  	signupArg.StoreSecret = true
   668  	_ = SignupFakeUserWithArg(tc, u, signupArg)
   669  
   670  	// add a pgp sibkey, pushed to server and stored locally (lksec)
   671  	arg := PGPKeyImportEngineArg{
   672  		Gen: &libkb.PGPGenArg{
   673  			PrimaryBits: 768,
   674  			SubkeyBits:  768,
   675  		},
   676  		PushSecret: true,
   677  	}
   678  	err := arg.Gen.MakeAllIds(tc.G)
   679  	require.NoError(t, err)
   680  	uis := libkb.UIs{
   681  		LogUI:    tc.G.UI.GetLogUI(),
   682  		SecretUI: u.NewSecretUI(),
   683  	}
   684  	eng := NewPGPKeyImportEngine(tc.G, arg)
   685  	m := NewMetaContextForTest(tc).WithUIs(uis)
   686  	err = RunEngine2(m, eng)
   687  	if err != nil {
   688  		tc.T.Fatal(err)
   689  	}
   690  
   691  	// This needs to happen *before* resetting the login state, as
   692  	// this call will cause the login state to be reloaded.
   693  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
   694  
   695  	tc.SimulateServiceRestart()
   696  
   697  	secretUI := libkb.TestSecretUI{}
   698  	uis = libkb.UIs{
   699  		LogUI:    tc.G.UI.GetLogUI(),
   700  		LoginUI:  &libkb.TestLoginUI{},
   701  		SecretUI: &secretUI,
   702  	}
   703  	beng := NewPaperKey(tc.G)
   704  	m = NewMetaContextForTest(tc).WithUIs(uis)
   705  	if err := RunEngine2(m, beng); err != nil {
   706  		t.Fatal(err)
   707  	}
   708  
   709  	if secretUI.CalledGetPassphrase {
   710  		t.Fatal("GetPassphrase() unexpectedly called")
   711  	}
   712  
   713  	backupPassphrase := beng.Passphrase()
   714  	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
   715  
   716  	Logout(tc)
   717  
   718  	newPassphrase := "password1234"
   719  	pcarg := &keybase1.PassphraseChangeArg{
   720  		Passphrase: newPassphrase,
   721  		Force:      true,
   722  	}
   723  	pceng := NewPassphraseChange(tc.G, pcarg)
   724  	if err := RunEngine2(m, pceng); err != nil {
   725  		t.Fatal(err)
   726  	}
   727  
   728  	verifyPassphraseChange(tc, u, newPassphrase)
   729  
   730  	u.Passphrase = newPassphrase
   731  	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
   732  	assertLoadPGPKeys(tc, u)
   733  }
   734  
   735  // test pp change when user has multiple 3sec encrypted pgp keys.
   736  func TestPassphraseChangePGP3SecMultiple(t *testing.T) {
   737  	tc := SetupEngineTest(t, "PassphraseChange")
   738  	defer tc.Cleanup()
   739  
   740  	u := createFakeUserWithPGPSibkeyPushed(tc)
   741  
   742  	// create/push another pgp key
   743  	parg := PGPKeyImportEngineArg{
   744  		Gen: &libkb.PGPGenArg{
   745  			PrimaryBits: 768,
   746  			SubkeyBits:  768,
   747  		},
   748  		PushSecret: true,
   749  		NoSave:     true,
   750  		AllowMulti: true,
   751  	}
   752  	err := parg.Gen.MakeAllIds(tc.G)
   753  	require.NoError(t, err)
   754  	uis := libkb.UIs{
   755  		LogUI:    tc.G.UI.GetLogUI(),
   756  		SecretUI: u.NewSecretUI(),
   757  	}
   758  	peng := NewPGPKeyImportEngine(tc.G, parg)
   759  	m := NewMetaContextForTest(tc).WithUIs(uis)
   760  	err = RunEngine2(m, peng)
   761  	if err != nil {
   762  		t.Fatal(err)
   763  	}
   764  
   765  	// clear the passphrase stream cache to force a prompt
   766  	// for the existing passphrase.
   767  	clearCaches(tc.G)
   768  
   769  	newPassphrase := "password1234"
   770  	arg := &keybase1.PassphraseChangeArg{
   771  		Passphrase: newPassphrase,
   772  	}
   773  	secui := u.NewSecretUI()
   774  	uis = libkb.UIs{
   775  		SecretUI: secui,
   776  	}
   777  	eng := NewPassphraseChange(tc.G, arg)
   778  	m = NewMetaContextForTest(tc).WithUIs(uis)
   779  	if err := RunEngine2(m, eng); err != nil {
   780  		t.Fatal(err)
   781  	}
   782  
   783  	verifyPassphraseChange(tc, u, newPassphrase)
   784  
   785  	if !secui.CalledGetPassphrase {
   786  		t.Errorf("get kb passphrase not called")
   787  	}
   788  
   789  	u.Passphrase = newPassphrase
   790  	assertLoadSecretKeys(tc, u, "passphrase change pgp")
   791  	assertLoadPGPKeys(tc, u)
   792  
   793  	me, err := libkb.LoadMe(libkb.NewLoadUserForceArg(tc.G))
   794  	if err != nil {
   795  		t.Fatal(err)
   796  	}
   797  	syncKeys, err := me.AllSyncedSecretKeys(m)
   798  	if err != nil {
   799  		t.Fatal(err)
   800  	}
   801  	if len(syncKeys) != 2 {
   802  		t.Errorf("num pgp sync keys: %d, expected 2", len(syncKeys))
   803  	}
   804  	for _, key := range syncKeys {
   805  		parg := libkb.SecretKeyPromptArg{
   806  			SecretUI: u.NewSecretUI(),
   807  		}
   808  		unlocked, err := key.PromptAndUnlock(m, parg, nil, me)
   809  		if err != nil {
   810  			t.Fatal(err)
   811  		}
   812  		if unlocked == nil {
   813  			t.Fatal("failed to unlock key")
   814  		}
   815  	}
   816  }
   817  
   818  // Make sure passphrase generations are stored properly alongside encrypted keys.
   819  // We'll create a user, check the ppgens of the initial pair of keys, change the
   820  // passphrase, create a new key, and then they the ppgen of that new one (which
   821  // should be higher).
   822  func TestPassphraseGenerationStored(t *testing.T) {
   823  	tc := SetupEngineTest(t, "PassphraseChange")
   824  	defer tc.Cleanup()
   825  
   826  	u := CreateAndSignupFakeUser(tc, "login")
   827  	mctx := tc.MetaContext()
   828  
   829  	// All of the keys initially created with the user should be stored as
   830  	// passphrase generation 1.
   831  	skbKeyringFile, err := libkb.LoadSKBKeyring(mctx, u.NormalizedUsername())
   832  	if err != nil {
   833  		t.Fatal(err)
   834  	}
   835  	initialGenerationOneCount := 0
   836  	for _, block := range skbKeyringFile.Blocks {
   837  		if block.Priv.PassphraseGeneration != 1 {
   838  			t.Fatalf("Expected all encrypted keys to be ppgen 1. Found %d.",
   839  				block.Priv.PassphraseGeneration)
   840  		}
   841  		initialGenerationOneCount++
   842  	}
   843  
   844  	//
   845  	// Do a passphrase change.
   846  	//
   847  	newPassphrase := "password1234"
   848  	arg := &keybase1.PassphraseChangeArg{
   849  		OldPassphrase: u.Passphrase,
   850  		Passphrase:    newPassphrase,
   851  	}
   852  	uis := libkb.UIs{
   853  		LogUI:    tc.G.UI.GetLogUI(),
   854  		SecretUI: u.NewSecretUI(),
   855  	}
   856  	eng := NewPassphraseChange(tc.G, arg)
   857  	m := NewMetaContextForTest(tc).WithUIs(uis)
   858  	if err := RunEngine2(m, eng); err != nil {
   859  		t.Fatal(err)
   860  	}
   861  	u.Passphrase = newPassphrase
   862  
   863  	//
   864  	// Now, generate a new key. This one should be stored with ppgen 2.
   865  	//
   866  	pgpArg := PGPKeyImportEngineArg{
   867  		Gen: &libkb.PGPGenArg{
   868  			PrimaryBits: 768,
   869  			SubkeyBits:  768,
   870  		},
   871  	}
   872  	err = pgpArg.Gen.MakeAllIds(tc.G)
   873  	require.NoError(t, err)
   874  	pgpEng := NewPGPKeyImportEngine(tc.G, pgpArg)
   875  	uis = libkb.UIs{
   876  		LogUI:    tc.G.UI.GetLogUI(),
   877  		SecretUI: u.NewSecretUI(),
   878  	}
   879  	m = NewMetaContextForTest(tc).WithUIs(uis)
   880  	err = RunEngine2(m, pgpEng)
   881  	if err != nil {
   882  		t.Fatal(err)
   883  	}
   884  
   885  	//
   886  	// Finally, check that the new key (and only the new key) is marked as ppgen 2.
   887  	//
   888  	finalSKBKeyringFile, err := libkb.LoadSKBKeyring(mctx, u.NormalizedUsername())
   889  	if err != nil {
   890  		t.Fatal(err)
   891  	}
   892  	finalGenOneCount := 0
   893  	finalGenTwoCount := 0
   894  	for _, block := range finalSKBKeyringFile.Blocks {
   895  		if block.Priv.PassphraseGeneration == 1 {
   896  			finalGenOneCount++
   897  		} else if block.Priv.PassphraseGeneration == 2 {
   898  			finalGenTwoCount++
   899  		} else {
   900  			t.Fatalf("Expected all encrypted keys to be ppgen 1 or 2. Found %d.",
   901  				block.Priv.PassphraseGeneration)
   902  		}
   903  	}
   904  	if finalGenOneCount != initialGenerationOneCount {
   905  		t.Fatalf("Expected initial count of ppgen 1 keys (%d) to equal final count (%d).",
   906  			initialGenerationOneCount, finalGenOneCount)
   907  	}
   908  	if finalGenTwoCount != 1 {
   909  		t.Fatalf("Expected one key in ppgen 2. Found %d keys.", finalGenTwoCount)
   910  	}
   911  }