github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/paperkey_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  	"testing"
     8  
     9  	"github.com/keybase/client/go/libkb"
    10  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  func paperDevs(tc libkb.TestContext, fu *FakeUser) (*libkb.User, []*libkb.Device) {
    15  	arg := libkb.NewLoadUserForceArg(tc.G).WithName(fu.Username)
    16  	u, err := libkb.LoadUser(arg)
    17  	require.NoError(tc.T, err)
    18  	cki := u.GetComputedKeyInfos()
    19  	require.NotNil(tc.T, cki)
    20  	return u, cki.PaperDevices()
    21  }
    22  
    23  func hasZeroPaperDev(tc libkb.TestContext, fu *FakeUser) {
    24  	_, bdevs := paperDevs(tc, fu)
    25  	require.Equal(tc.T, 0, len(bdevs), "num backup devices")
    26  }
    27  
    28  func hasOnePaperDev(tc libkb.TestContext, fu *FakeUser) keybase1.DeviceID {
    29  	u, bdevs := paperDevs(tc, fu)
    30  
    31  	require.Equal(tc.T, 1, len(bdevs), "num backup devices")
    32  
    33  	devid := bdevs[0].ID
    34  	sibkey, err := u.GetComputedKeyFamily().GetSibkeyForDevice(devid)
    35  	require.NoError(tc.T, err)
    36  	require.NotNil(tc.T, sibkey)
    37  
    38  	enckey, err := u.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(devid)
    39  	require.NoError(tc.T, err)
    40  	require.NotNil(tc.T, enckey)
    41  
    42  	return devid
    43  }
    44  
    45  func TestPaperKey(t *testing.T) {
    46  	tc := SetupEngineTest(t, "backup")
    47  	defer tc.Cleanup()
    48  
    49  	f := func(arg *SignupEngineRunArg) {
    50  		arg.SkipPaper = true
    51  	}
    52  
    53  	fu, _, _ := CreateAndSignupFakeUserCustomArg(tc, "login", f)
    54  
    55  	userDeviceID := tc.G.Env.GetDeviceID()
    56  
    57  	uis := libkb.UIs{
    58  		LogUI:    tc.G.UI.GetLogUI(),
    59  		LoginUI:  &libkb.TestLoginUI{},
    60  		SecretUI: &libkb.TestSecretUI{},
    61  	}
    62  	eng := NewPaperKey(tc.G)
    63  	m := NewMetaContextForTest(tc).WithUIs(uis)
    64  	err := RunEngine2(m, eng)
    65  	require.NoError(t, err)
    66  	require.NotZero(t, len(eng.Passphrase()))
    67  	Logout(tc)
    68  
    69  	// check for the backup key
    70  	devid := hasOnePaperDev(tc, fu)
    71  
    72  	// ok, just log in again:
    73  	err = fu.Login(tc.G)
    74  	require.NoError(t, err)
    75  	Logout(tc)
    76  
    77  	// make sure the passphrase authentication didn't change:
    78  	m = m.WithNewProvisionalLoginContext()
    79  	err = libkb.PassphraseLoginNoPrompt(m, fu.Username, fu.Passphrase)
    80  	require.NoError(t, err, "passphrase login still worked")
    81  	m.CommitProvisionalLogin()
    82  
    83  	// make sure the backup key device id is different than the actual device id
    84  	// and that the actual device id didn't change.
    85  	// (investigating bug theory)
    86  	require.NotEqual(t, userDeviceID, devid)
    87  	require.Equal(t, userDeviceID, tc.G.Env.GetDeviceID())
    88  	require.NotEqual(t, tc.G.Env.GetDeviceID(), devid)
    89  }
    90  
    91  func TestPaperKeyMulti(t *testing.T) {
    92  	testPaperKeyMulti(t, false)
    93  }
    94  
    95  func TestPaperKeyMultiPUK(t *testing.T) {
    96  	testPaperKeyMulti(t, true)
    97  }
    98  
    99  // Generate multiple paper keys
   100  func testPaperKeyMulti(t *testing.T, upgradePerUserKey bool) {
   101  	tc := SetupEngineTest(t, "backup")
   102  	defer tc.Cleanup()
   103  	tc.Tp.DisableUpgradePerUserKey = !upgradePerUserKey
   104  
   105  	f := func(arg *SignupEngineRunArg) {
   106  		arg.SkipPaper = true
   107  	}
   108  
   109  	fu, _, _ := CreateAndSignupFakeUserCustomArg(tc, "login", f)
   110  
   111  	for i := 0; i < 3; i++ {
   112  		uis := libkb.UIs{
   113  			LogUI:    tc.G.UI.GetLogUI(),
   114  			LoginUI:  &libkb.TestLoginUI{},
   115  			SecretUI: &libkb.TestSecretUI{},
   116  		}
   117  		eng := NewPaperKey(tc.G)
   118  		m := NewMetaContextForTest(tc).WithUIs(uis)
   119  		err := RunEngine2(m, eng)
   120  		require.NoError(t, err)
   121  		require.NotZero(t, eng.Passphrase())
   122  
   123  		// check for the backup key
   124  		_, bdevs := paperDevs(tc, fu)
   125  		require.Equal(tc.T, i+1, len(bdevs), "num backup devices")
   126  	}
   127  }
   128  
   129  // tests revoking of existing backup keys
   130  func TestPaperKeyRevoke(t *testing.T) {
   131  	tc := SetupEngineTest(t, "backup")
   132  	defer tc.Cleanup()
   133  
   134  	fu := CreateAndSignupFakeUser(tc, "login")
   135  
   136  	uis := libkb.UIs{
   137  		LogUI:    tc.G.UI.GetLogUI(),
   138  		LoginUI:  &libkb.TestLoginUI{RevokeBackup: true},
   139  		SecretUI: &libkb.TestSecretUI{},
   140  	}
   141  
   142  	eng := NewPaperKey(tc.G)
   143  	m := NewMetaContextForTest(tc).WithUIs(uis)
   144  	err := RunEngine2(m, eng)
   145  	require.NoError(t, err)
   146  	require.NotZero(t, len(eng.Passphrase()))
   147  
   148  	// check for the backup key
   149  	_, bdevs := paperDevs(tc, fu)
   150  	require.Len(t, bdevs, 1)
   151  
   152  	// generate another one, first should be revoked
   153  	eng = NewPaperKey(tc.G)
   154  	err = RunEngine2(m, eng)
   155  	require.NoError(t, err)
   156  	require.NotZero(t, len(eng.Passphrase()))
   157  
   158  	// check for the backup key
   159  	_, bdevs = paperDevs(tc, fu)
   160  	require.Len(t, bdevs, 1)
   161  }
   162  
   163  // make a paperkey after revoking a previous one
   164  func TestPaperKeyAfterRevokePUK(t *testing.T) {
   165  	tc := SetupEngineTest(t, "backup")
   166  	defer tc.Cleanup()
   167  
   168  	fu := CreateAndSignupFakeUser(tc, "login")
   169  
   170  	gen := func() {
   171  		uis := libkb.UIs{
   172  			LogUI:    tc.G.UI.GetLogUI(),
   173  			LoginUI:  &libkb.TestLoginUI{},
   174  			SecretUI: &libkb.TestSecretUI{},
   175  		}
   176  		eng := NewPaperKey(tc.G)
   177  		m := NewMetaContextForTest(tc).WithUIs(uis)
   178  		err := RunEngine2(m, eng)
   179  		require.NoError(t, err)
   180  		require.NotEqual(t, 0, len(eng.Passphrase()), "empty passphrase")
   181  	}
   182  
   183  	revoke := func(devid keybase1.DeviceID) {
   184  		err := doRevokeDevice(tc, fu, devid, false /* force */, false /* forceLast */)
   185  		require.NoError(t, err)
   186  	}
   187  
   188  	hasZeroPaperDev(tc, fu)
   189  	gen()
   190  	devid := hasOnePaperDev(tc, fu)
   191  	revoke(devid)
   192  	hasZeroPaperDev(tc, fu)
   193  	gen()
   194  	hasOnePaperDev(tc, fu)
   195  }
   196  
   197  // tests not revoking existing backup keys
   198  func TestPaperKeyNoRevoke(t *testing.T) {
   199  	tc := SetupEngineTest(t, "backup")
   200  	defer tc.Cleanup()
   201  
   202  	fu := CreateAndSignupFakeUserPaper(tc, "login")
   203  
   204  	uis := libkb.UIs{
   205  		LogUI:    tc.G.UI.GetLogUI(),
   206  		LoginUI:  &libkb.TestLoginUI{RevokeBackup: false},
   207  		SecretUI: &libkb.TestSecretUI{},
   208  	}
   209  
   210  	eng := NewPaperKey(tc.G)
   211  	m := NewMetaContextForTest(tc).WithUIs(uis)
   212  	err := RunEngine2(m, eng)
   213  	require.NoError(t, err)
   214  	require.NotZero(t, len(eng.Passphrase()))
   215  
   216  	// check for the backup key
   217  	_, bdevs := paperDevs(tc, fu)
   218  	require.Len(t, bdevs, 2)
   219  
   220  	// generate another one, first should be left alone
   221  	eng = NewPaperKey(tc.G)
   222  	err = RunEngine2(m, eng)
   223  	require.NoError(t, err)
   224  	require.NotZero(t, len(eng.Passphrase()))
   225  
   226  	// check for the backup key
   227  	_, bdevs = paperDevs(tc, fu)
   228  	require.Len(t, bdevs, 3)
   229  }
   230  
   231  // Make sure PaperKeyGen uses the secret store.
   232  func TestPaperKeyGenWithSecretStore(t *testing.T) {
   233  	testEngineWithSecretStore(t, func(
   234  		tc libkb.TestContext, fu *FakeUser, secretUI libkb.SecretUI) {
   235  		uis := libkb.UIs{
   236  			LogUI:    tc.G.UI.GetLogUI(),
   237  			LoginUI:  &libkb.TestLoginUI{},
   238  			SecretUI: secretUI,
   239  		}
   240  		eng := NewPaperKey(tc.G)
   241  		m := NewMetaContextForTest(tc).WithUIs(uis)
   242  		err := RunEngine2(m, eng)
   243  		require.NoError(t, err)
   244  	})
   245  }