github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/saltpackkeys/saltpack_recipient_keyfinder_engine_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  package saltpackkeys
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  	"encoding/hex"
     9  	"fmt"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/keybase/client/go/engine"
    15  	"github.com/keybase/client/go/externalstest"
    16  	"github.com/keybase/client/go/kbtest"
    17  	"github.com/keybase/client/go/libkb"
    18  	"github.com/keybase/client/go/protocol/keybase1"
    19  	"github.com/keybase/client/go/teams"
    20  	insecureTriplesec "github.com/keybase/go-triplesec-insecure"
    21  )
    22  
    23  func InstallInsecureTriplesec(g *libkb.GlobalContext) {
    24  	g.NewTriplesec = func(passphrase []byte, salt []byte) (libkb.Triplesec, error) {
    25  		warner := func() { g.Log.Warning("Installing insecure Triplesec with weak stretch parameters") }
    26  		isProduction := func() bool {
    27  			return g.Env.GetRunMode() == libkb.ProductionRunMode
    28  		}
    29  		return insecureTriplesec.NewCipher(passphrase, salt, libkb.ClientTriplesecVersion, warner, isProduction)
    30  	}
    31  }
    32  
    33  func SetupKeyfinderEngineTest(tb libkb.TestingTB, name string) (tc libkb.TestContext) {
    34  	// SetupTest ignores the depth argument, so we can safely pass 0.
    35  	tc = externalstest.SetupTest(tb, name, 0)
    36  
    37  	// use an insecure triplesec in tests
    38  	InstallInsecureTriplesec(tc.G)
    39  
    40  	return tc
    41  
    42  }
    43  
    44  func TestSaltpackRecipientKeyfinderPUKs(t *testing.T) {
    45  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
    46  	defer tc.Cleanup()
    47  
    48  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
    49  	require.NoError(t, err)
    50  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
    51  	require.NoError(t, err)
    52  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
    53  	require.NoError(t, err)
    54  
    55  	trackUI := &kbtest.FakeIdentifyUI{
    56  		Proofs: make(map[string]string),
    57  	}
    58  
    59  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
    60  	arg := libkb.SaltpackRecipientKeyfinderArg{
    61  		Recipients:    []string{u1.Username, u2.Username, u3.Username},
    62  		UseEntityKeys: true,
    63  		// Since no user has a paper key, this option should not lead to the addition of any keys.
    64  		UsePaperKeys: true,
    65  	}
    66  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
    67  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
    68  	if err := engine.RunEngine2(m, eng); err != nil {
    69  		t.Fatal(err)
    70  	}
    71  
    72  	fDHKeys := eng.GetPublicKIDs()
    73  	if len(fDHKeys) != 3 {
    74  		t.Errorf("number of per user keys found: %d, expected 3", len(fDHKeys))
    75  	}
    76  	fDHKeyset := make(map[keybase1.KID]struct{})
    77  	for _, fPUK := range fDHKeys {
    78  		fDHKeyset[fPUK] = struct{}{}
    79  	}
    80  	KID := u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
    81  	if _, ok := fDHKeyset[KID]; !ok {
    82  		t.Errorf("expected to find key %v, which was not retrieved", KID)
    83  	}
    84  	KID = u2.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
    85  	if _, ok := fDHKeyset[KID]; !ok {
    86  		t.Errorf("expected to find key %v, which was not retrieved", KID)
    87  	}
    88  	KID = u3.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
    89  	if _, ok := fDHKeyset[KID]; !ok {
    90  		t.Errorf("expected to find key %v, which was not retrieved", KID)
    91  	}
    92  
    93  	symKeys := eng.GetSymmetricKeys()
    94  	if len(symKeys) != 0 {
    95  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
    96  	}
    97  
    98  }
    99  
   100  func TestSaltpackRecipientKeyfinderFailsOnNonExistingUserWithoutLogin(t *testing.T) {
   101  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   102  	defer tc.Cleanup()
   103  
   104  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   105  	require.NoError(t, err)
   106  	kbtest.Logout(tc)
   107  
   108  	trackUI := &kbtest.FakeIdentifyUI{
   109  		Proofs: make(map[string]string),
   110  	}
   111  
   112  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   113  	arg := libkb.SaltpackRecipientKeyfinderArg{
   114  		Recipients:    []string{"not_a_user"},
   115  		UseEntityKeys: true,
   116  		NoSelfEncrypt: true,
   117  	}
   118  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   119  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   120  	err = engine.RunEngine2(m, eng)
   121  	_, ok := engine.RunEngine2(m, eng).(libkb.RecipientNotFoundError)
   122  	require.True(t, ok, err.Error())
   123  }
   124  
   125  func TestSaltpackRecipientKeyfinderFailsOnNonExistingUserWithLogin(t *testing.T) {
   126  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   127  	defer tc.Cleanup()
   128  
   129  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   130  	require.NoError(t, err)
   131  
   132  	trackUI := &kbtest.FakeIdentifyUI{
   133  		Proofs: make(map[string]string),
   134  	}
   135  
   136  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   137  	arg := libkb.SaltpackRecipientKeyfinderArg{
   138  		Recipients:    []string{"not_a_user"},
   139  		UseEntityKeys: true,
   140  	}
   141  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   142  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   143  	err = engine.RunEngine2(m, eng)
   144  	_, ok := engine.RunEngine2(m, eng).(libkb.RecipientNotFoundError)
   145  	require.True(t, ok, err.Error())
   146  }
   147  
   148  func TestSaltpackRecipientKeyfinderPUKSelfEncrypt(t *testing.T) {
   149  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   150  	defer tc.Cleanup()
   151  
   152  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   153  	require.NoError(t, err)
   154  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   155  	require.NoError(t, err)
   156  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   157  	require.NoError(t, err)
   158  
   159  	trackUI := &kbtest.FakeIdentifyUI{
   160  		Proofs: make(map[string]string),
   161  	}
   162  
   163  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   164  	arg := libkb.SaltpackRecipientKeyfinderArg{
   165  		Recipients:    []string{u1.Username, u2.Username},
   166  		UseEntityKeys: true,
   167  	}
   168  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   169  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   170  	if err := engine.RunEngine2(m, eng); err != nil {
   171  		t.Fatal(err)
   172  	}
   173  
   174  	fDHKeys := eng.GetPublicKIDs()
   175  	if len(fDHKeys) != 3 {
   176  		t.Errorf("number of per user keys found: %d, expected 3", len(fDHKeys))
   177  	}
   178  	fDHKeyset := make(map[keybase1.KID]struct{})
   179  	for _, fPUK := range fDHKeys {
   180  		fDHKeyset[fPUK] = struct{}{}
   181  	}
   182  	KID := u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   183  	if _, ok := fDHKeyset[KID]; !ok {
   184  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   185  	}
   186  	KID = u2.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   187  	if _, ok := fDHKeyset[KID]; !ok {
   188  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   189  	}
   190  	KID = u3.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   191  	if _, ok := fDHKeyset[KID]; !ok {
   192  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   193  	}
   194  
   195  	symKeys := eng.GetSymmetricKeys()
   196  	if len(symKeys) != 0 {
   197  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
   198  	}
   199  
   200  }
   201  
   202  func TestSaltpackRecipientKeyfinderPUKNoSelfEncrypt(t *testing.T) {
   203  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   204  	defer tc.Cleanup()
   205  
   206  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   207  	require.NoError(t, err)
   208  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   209  	require.NoError(t, err)
   210  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   211  	require.NoError(t, err)
   212  
   213  	trackUI := &kbtest.FakeIdentifyUI{
   214  		Proofs: make(map[string]string),
   215  	}
   216  
   217  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   218  	arg := libkb.SaltpackRecipientKeyfinderArg{
   219  		Recipients:    []string{u1.Username, u2.Username},
   220  		UseEntityKeys: true,
   221  		NoSelfEncrypt: true, // Since this is set, u3's keys should NOT be included.
   222  	}
   223  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   224  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   225  	if err := engine.RunEngine2(m, eng); err != nil {
   226  		t.Fatal(err)
   227  	}
   228  
   229  	fDHKeys := eng.GetPublicKIDs()
   230  	if len(fDHKeys) != 2 {
   231  		t.Errorf("number of per user keys found: %d, expected 2", len(fDHKeys))
   232  	}
   233  	fDHKeyset := make(map[keybase1.KID]struct{})
   234  	for _, fPUK := range fDHKeys {
   235  		fDHKeyset[fPUK] = struct{}{}
   236  	}
   237  	KID := u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   238  	if _, ok := fDHKeyset[KID]; !ok {
   239  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   240  	}
   241  	KID = u2.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   242  	if _, ok := fDHKeyset[KID]; !ok {
   243  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   244  	}
   245  
   246  	symKeys := eng.GetSymmetricKeys()
   247  	if len(symKeys) != 0 {
   248  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
   249  	}
   250  
   251  }
   252  
   253  func TestSaltpackRecipientKeyfinderCreatesImplicitTeamIfUserHasNoPUK(t *testing.T) {
   254  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   255  	defer tc.Cleanup()
   256  	teams.ServiceInit(tc.G)
   257  
   258  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   259  	require.NoError(t, err)
   260  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   261  	require.NoError(t, err)
   262  
   263  	trackUI := &kbtest.FakeIdentifyUI{
   264  		Proofs: make(map[string]string),
   265  	}
   266  
   267  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u2.NewSecretUI()}
   268  	arg := libkb.SaltpackRecipientKeyfinderArg{
   269  		Recipients:    []string{u1.Username},
   270  		UseEntityKeys: true,
   271  	}
   272  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   273  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   274  
   275  	// This should work with no errors, as both users exist and have PUKs
   276  	if err := engine.RunEngine2(m, eng); err != nil {
   277  		t.Fatal(err)
   278  	}
   279  	fDHKeys := eng.GetPublicKIDs()
   280  	if len(fDHKeys) != 2 {
   281  		t.Errorf("number of per user keys found: %d, expected 2", len(fDHKeys))
   282  	}
   283  	fDHKeyset := make(map[keybase1.KID]struct{})
   284  	for _, fPUK := range fDHKeys {
   285  		fDHKeyset[fPUK] = struct{}{}
   286  	}
   287  	KID := u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   288  	if _, ok := fDHKeyset[KID]; !ok {
   289  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   290  	}
   291  	KID = u2.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   292  	if _, ok := fDHKeyset[KID]; !ok {
   293  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   294  	}
   295  
   296  	require.Empty(t, eng.GetSymmetricKeys())
   297  
   298  	// Now, let's create a user without PUK
   299  	tc.Tp.DisableUpgradePerUserKey = true
   300  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   301  	require.NoError(t, err)
   302  	kbtest.Logout(tc)
   303  
   304  	err = u2.Login(tc.G)
   305  	require.NoError(t, err)
   306  
   307  	// This should create an implicit team, as u3 has no PUK
   308  	arg = libkb.SaltpackRecipientKeyfinderArg{
   309  		Recipients:    []string{u1.Username, u3.Username},
   310  		UseEntityKeys: true,
   311  	}
   312  	eng = NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   313  	err = engine.RunEngine2(m, eng)
   314  	require.NoError(t, err)
   315  	fDHKeys = eng.GetPublicKIDs()
   316  	if len(fDHKeys) != 2 {
   317  		t.Errorf("number of per user keys found: %d, expected 2", len(fDHKeys))
   318  	}
   319  	fDHKeyset = make(map[keybase1.KID]struct{})
   320  	for _, fPUK := range fDHKeys {
   321  		fDHKeyset[fPUK] = struct{}{}
   322  	}
   323  	KID = u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   324  	if _, ok := fDHKeyset[KID]; !ok {
   325  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   326  	}
   327  	KID = u2.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   328  	if _, ok := fDHKeyset[KID]; !ok {
   329  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   330  	}
   331  
   332  	symKeys := eng.GetSymmetricKeys()
   333  	require.Len(t, symKeys, 1)
   334  	team, _, _, err := teams.LookupImplicitTeam(m.Ctx(), m.G(), u2.Username+","+u3.Username, false, teams.ImplicitTeamOptions{})
   335  	require.NoError(t, err)
   336  	teamSaltpackKey, err := team.SaltpackEncryptionKeyLatest(m.Ctx())
   337  	require.NoError(t, err)
   338  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
   339  }
   340  
   341  func TestSaltpackRecipientKeyfinderDeviceKeys(t *testing.T) {
   342  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   343  	defer tc.Cleanup()
   344  
   345  	u1, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   346  	require.NoError(t, err)
   347  
   348  	// u2 has 2 devices
   349  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   350  	require.NoError(t, err)
   351  	tcY := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine2") // context for second device
   352  	defer tcY.Cleanup()
   353  	kbtest.ProvisionNewDeviceKex(&tc, &tcY, u2, keybase1.DeviceTypeV2_DESKTOP)
   354  	m := libkb.NewMetaContextForTest(tc)
   355  	tc.G.BustLocalUserCache(m.Ctx(), u2.GetUID())
   356  	tc.G.GetUPAKLoader().ClearMemory()
   357  	u2new, err := libkb.LoadMe(libkb.NewLoadUserArgWithMetaContext(m))
   358  	require.NoError(t, err)
   359  
   360  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   361  	require.NoError(t, err)
   362  
   363  	trackUI := &kbtest.FakeIdentifyUI{
   364  		Proofs: make(map[string]string),
   365  	}
   366  
   367  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   368  	arg := libkb.SaltpackRecipientKeyfinderArg{
   369  		Recipients:    []string{u1.Username, u2.Username, u3.Username},
   370  		UseDeviceKeys: true,
   371  	}
   372  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   373  	m = m.WithUIs(uis)
   374  	if err := engine.RunEngine2(m, eng); err != nil {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	fDHKeys := eng.GetPublicKIDs()
   379  	if len(fDHKeys) != 4 {
   380  		t.Errorf("number of device keys found: %d, expected 4", len(fDHKeys))
   381  	}
   382  	fDHKeyset := make(map[keybase1.KID]struct{})
   383  	for _, fPUK := range fDHKeys {
   384  		fDHKeyset[fPUK] = struct{}{}
   385  	}
   386  
   387  	u1Device, err := selectOneActiveNonPaperDeviceID(u1.User)
   388  	require.NoError(t, err)
   389  	key, err := u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u1Device)
   390  	require.NoError(t, err)
   391  	KID := key.GetKID()
   392  	if _, ok := fDHKeyset[KID]; !ok {
   393  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   394  	}
   395  	key, err = u2new.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u2new.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   396  	require.NoError(t, err)
   397  	KID = key.GetKID()
   398  	if _, ok := fDHKeyset[KID]; !ok {
   399  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   400  	}
   401  	key, err = u2new.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u2new.GetComputedKeyFamily().GetAllActiveDevices()[1].ID)
   402  	require.NoError(t, err)
   403  	KID = key.GetKID()
   404  	if _, ok := fDHKeyset[KID]; !ok {
   405  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   406  	}
   407  	key, err = u3.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u3.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   408  	require.NoError(t, err)
   409  	KID = key.GetKID()
   410  	if _, ok := fDHKeyset[KID]; !ok {
   411  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   412  	}
   413  
   414  	symKeys := eng.GetSymmetricKeys()
   415  	if len(symKeys) != 0 {
   416  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
   417  	}
   418  
   419  }
   420  
   421  func TestSaltpackRecipientKeyfinderSkipsMissingKeys(t *testing.T) {
   422  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   423  	defer tc.Cleanup()
   424  
   425  	u1, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   426  	require.NoError(t, err)
   427  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   428  	require.NoError(t, err)
   429  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   430  	require.NoError(t, err)
   431  
   432  	trackUI := &kbtest.FakeIdentifyUI{
   433  		Proofs: make(map[string]string),
   434  	}
   435  
   436  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   437  	arg := libkb.SaltpackRecipientKeyfinderArg{
   438  		Recipients:    []string{u1.Username, u2.Username, u3.Username},
   439  		UseDeviceKeys: true,
   440  		UsePaperKeys:  true, // only u1 has a paper key
   441  	}
   442  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   443  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   444  	if err := engine.RunEngine2(m, eng); err != nil {
   445  		t.Fatal(err)
   446  	}
   447  
   448  	fDHKeys := eng.GetPublicKIDs()
   449  	if len(fDHKeys) != 4 {
   450  		t.Errorf("number of device keys found: %d, expected 4", len(fDHKeys))
   451  	}
   452  	fDHKeyset := make(map[keybase1.KID]struct{})
   453  	for _, fPUK := range fDHKeys {
   454  		fDHKeyset[fPUK] = struct{}{}
   455  	}
   456  
   457  	key, err := u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u1.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   458  	require.NoError(t, err)
   459  	KID := key.GetKID()
   460  	if _, ok := fDHKeyset[KID]; !ok {
   461  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   462  	}
   463  	key, err = u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u1.User.GetComputedKeyFamily().GetAllActiveDevices()[1].ID)
   464  	require.NoError(t, err)
   465  	KID = key.GetKID()
   466  	if _, ok := fDHKeyset[KID]; !ok {
   467  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   468  	}
   469  	key, err = u2.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u2.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   470  	require.NoError(t, err)
   471  	KID = key.GetKID()
   472  	if _, ok := fDHKeyset[KID]; !ok {
   473  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   474  	}
   475  	key, err = u3.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u3.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   476  	require.NoError(t, err)
   477  	KID = key.GetKID()
   478  	if _, ok := fDHKeyset[KID]; !ok {
   479  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   480  	}
   481  
   482  	symKeys := eng.GetSymmetricKeys()
   483  	if len(symKeys) != 0 {
   484  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
   485  	}
   486  
   487  }
   488  
   489  func selectOneActivePaperDeviceID(u *libkb.User) (keybase1.DeviceID, error) {
   490  	for _, d := range u.GetComputedKeyFamily().GetAllActiveDevices() {
   491  		if d.Type == keybase1.DeviceTypeV2_PAPER {
   492  			return d.ID, nil
   493  		}
   494  	}
   495  	return "", fmt.Errorf("No paper devices found")
   496  }
   497  
   498  func selectOneActiveNonPaperDeviceID(u *libkb.User) (keybase1.DeviceID, error) {
   499  	for _, d := range u.GetComputedKeyFamily().GetAllActiveDevices() {
   500  		if d.Type != keybase1.DeviceTypeV2_PAPER {
   501  			return d.ID, nil
   502  		}
   503  	}
   504  	return "", fmt.Errorf("No paper devices found")
   505  }
   506  
   507  func TestSaltpackRecipientKeyfinderPaperKeys(t *testing.T) {
   508  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   509  	defer tc.Cleanup()
   510  
   511  	u1, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   512  	require.NoError(t, err)
   513  	u2, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   514  	require.NoError(t, err)
   515  	u3, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   516  	require.NoError(t, err)
   517  
   518  	trackUI := &kbtest.FakeIdentifyUI{
   519  		Proofs: make(map[string]string),
   520  	}
   521  
   522  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   523  	arg := libkb.SaltpackRecipientKeyfinderArg{
   524  		Recipients:   []string{u1.Username, u2.Username, u3.Username},
   525  		UsePaperKeys: true,
   526  	}
   527  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   528  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   529  	if err := engine.RunEngine2(m, eng); err != nil {
   530  		t.Fatal(err)
   531  	}
   532  
   533  	fDHKeys := eng.GetPublicKIDs()
   534  	if len(fDHKeys) != 3 {
   535  		t.Errorf("number of device keys found: %d, expected 3", len(fDHKeys))
   536  	}
   537  	fDHKeyset := make(map[keybase1.KID]struct{})
   538  	for _, fPUK := range fDHKeys {
   539  		fDHKeyset[fPUK] = struct{}{}
   540  	}
   541  
   542  	id, err := selectOneActivePaperDeviceID(u1.User)
   543  	require.NoError(t, err)
   544  	key, err := u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(id)
   545  	require.NoError(t, err)
   546  	KID := key.GetKID()
   547  	if _, ok := fDHKeyset[KID]; !ok {
   548  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   549  	}
   550  	id, err = selectOneActivePaperDeviceID(u1.User)
   551  	require.NoError(t, err)
   552  	key, err = u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(id)
   553  	require.NoError(t, err)
   554  	KID = key.GetKID()
   555  	if _, ok := fDHKeyset[KID]; !ok {
   556  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   557  	}
   558  	id, err = selectOneActivePaperDeviceID(u1.User)
   559  	require.NoError(t, err)
   560  	key, err = u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(id)
   561  	require.NoError(t, err)
   562  	KID = key.GetKID()
   563  	if _, ok := fDHKeyset[KID]; !ok {
   564  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   565  	}
   566  
   567  	symKeys := eng.GetSymmetricKeys()
   568  	if len(symKeys) != 0 {
   569  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
   570  	}
   571  }
   572  
   573  func TestSaltpackRecipientKeyfinderDevicePaperAndPerUserKeys(t *testing.T) {
   574  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   575  	defer tc.Cleanup()
   576  
   577  	u1, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   578  	require.NoError(t, err)
   579  
   580  	// u2 has 2 devices + 1 paper device
   581  	u2, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   582  	require.NoError(t, err)
   583  	tcY := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine2") // context for second device
   584  	defer tcY.Cleanup()
   585  	kbtest.ProvisionNewDeviceKex(&tc, &tcY, u2, keybase1.DeviceTypeV2_DESKTOP)
   586  	m := libkb.NewMetaContextForTest(tc)
   587  	tc.G.BustLocalUserCache(m.Ctx(), u2.GetUID())
   588  	tc.G.GetUPAKLoader().ClearMemory()
   589  	u2new, err := libkb.LoadMe(libkb.NewLoadUserArgWithMetaContext(m))
   590  	require.NoError(t, err)
   591  
   592  	u3, err := kbtest.CreateAndSignupFakeUserPaper("spkfe", tc.G)
   593  	require.NoError(t, err)
   594  
   595  	trackUI := &kbtest.FakeIdentifyUI{
   596  		Proofs: make(map[string]string),
   597  	}
   598  
   599  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   600  	arg := libkb.SaltpackRecipientKeyfinderArg{
   601  		Recipients:    []string{u1.Username, u2.Username, u3.Username},
   602  		UseDeviceKeys: true,
   603  		UsePaperKeys:  true,
   604  		UseEntityKeys: true,
   605  	}
   606  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   607  	m = m.WithUIs(uis)
   608  	if err := engine.RunEngine2(m, eng); err != nil {
   609  		t.Fatal(err)
   610  	}
   611  
   612  	fDHKeys := eng.GetPublicKIDs()
   613  	if len(fDHKeys) != 10 { // 3 keys per user (1 paper, 1 device, 1 puk), plus an extra device for u2
   614  		t.Errorf("number of device keys found: %d, expected 4", len(fDHKeys))
   615  	}
   616  	fDHKeyset := make(map[keybase1.KID]struct{})
   617  	for _, fPUK := range fDHKeys {
   618  		fDHKeyset[fPUK] = struct{}{}
   619  	}
   620  
   621  	allKeyFamilies := []*libkb.ComputedKeyFamily{}
   622  	allKeyFamilies = append(allKeyFamilies, u1.User.GetComputedKeyFamily())
   623  	allKeyFamilies = append(allKeyFamilies, u2new.GetComputedKeyFamily())
   624  	allKeyFamilies = append(allKeyFamilies, u3.User.GetComputedKeyFamily())
   625  
   626  	var allKIDs []keybase1.KID
   627  	for _, kf := range allKeyFamilies {
   628  		for _, d := range kf.GetAllActiveDevices() {
   629  			k, err := kf.GetEncryptionSubkeyForDevice(d.ID)
   630  			require.NoError(t, err)
   631  			allKIDs = append(allKIDs, k.GetKID())
   632  		}
   633  		allKIDs = append(allKIDs, kf.GetLatestPerUserKey().EncKID)
   634  	}
   635  	require.Equal(t, 10, len(allKIDs)) // 3 keys for u1 and u3 (1 paper, 1 device, 1 puk), 4 for u2 (has 2 devices)
   636  
   637  	for _, KID := range allKIDs {
   638  		if _, ok := fDHKeyset[KID]; !ok {
   639  			t.Errorf("expected to find key %v, which was not retrieved", KID)
   640  		}
   641  	}
   642  	symKeys := eng.GetSymmetricKeys()
   643  	if len(symKeys) != 0 {
   644  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
   645  	}
   646  }
   647  
   648  func TestSaltpackRecipientKeyfinderExistingUserAssertions(t *testing.T) {
   649  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   650  	defer tc.Cleanup()
   651  
   652  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   653  	require.NoError(t, err)
   654  
   655  	trackUI := &kbtest.FakeIdentifyUI{
   656  		Proofs: make(map[string]string),
   657  	}
   658  
   659  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u1.NewSecretUI()}
   660  	arg := libkb.SaltpackRecipientKeyfinderArg{
   661  		Recipients:    []string{"t_tracy+t_tracy@rooter", "t_george", "t_kb+gbrltest@twitter"},
   662  		UseDeviceKeys: true,
   663  		NoSelfEncrypt: true,
   664  	}
   665  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   666  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   667  	if err := engine.RunEngine2(m, eng); err != nil {
   668  		t.Fatal(err)
   669  	}
   670  
   671  	fDHKeys := eng.GetPublicKIDs()
   672  	if len(fDHKeys) != 6 { // t_tracy has 1 device (+ a paper key, excluded here), t_george has 2 devices and a web key, t_kb has a device and a web key.
   673  		t.Errorf("number of DH keys found: %d, expected 6", len(fDHKeys))
   674  	}
   675  
   676  	symKeys := eng.GetSymmetricKeys()
   677  	if len(symKeys) != 0 {
   678  		t.Errorf("number of symmetric keys found: %d, expected 0", len(symKeys))
   679  	}
   680  
   681  }
   682  
   683  func createTeam(tc libkb.TestContext) (keybase1.TeamID, string) {
   684  	teams.ServiceInit(tc.G)
   685  
   686  	b, err := libkb.RandBytes(4)
   687  	require.NoError(tc.T, err)
   688  	name := "t_" + hex.EncodeToString(b)
   689  	teamID, err := teams.CreateRootTeam(context.TODO(), tc.G, name, keybase1.TeamSettings{})
   690  	require.NoError(tc.T, err)
   691  	require.NotNil(tc.T, teamID)
   692  
   693  	return *teamID, name
   694  }
   695  
   696  func TestSaltpackRecipientKeyfinderTeamBasic(t *testing.T) {
   697  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   698  	defer tc.Cleanup()
   699  
   700  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   701  	require.NoError(t, err)
   702  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   703  	require.NoError(t, err)
   704  
   705  	_, teamName := createTeam(tc)
   706  	_, err = teams.AddMember(context.TODO(), tc.G, teamName, u1.Username, keybase1.TeamRole_WRITER, nil)
   707  	require.NoError(t, err)
   708  
   709  	u3, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   710  	require.NoError(t, err)
   711  
   712  	err = u3.Login(tc.G)
   713  	require.NoError(t, err)
   714  
   715  	trackUI := &kbtest.FakeIdentifyUI{
   716  		Proofs: make(map[string]string),
   717  	}
   718  
   719  	// u3 is not part of the team, keyfinding should fail.
   720  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u3.NewSecretUI()}
   721  	arg := libkb.SaltpackRecipientKeyfinderArg{
   722  		TeamRecipients: []string{teamName},
   723  		UseEntityKeys:  true,
   724  	}
   725  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   726  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   727  	err = engine.RunEngine2(m, eng)
   728  	if e, ok := err.(libkb.AppStatusError); !ok || e.Code != libkb.SCTeamReadError {
   729  		t.Fatalf("expected error type libkb.AppStatusError with code %v, got %T (%+v)", libkb.SCTeamReadError, err, err)
   730  	}
   731  	kbtest.Logout(tc)
   732  
   733  	// u2 is part of the team, keyfinding should succeed.
   734  	err = u2.Login(tc.G)
   735  	require.NoError(t, err)
   736  	uis = libkb.UIs{IdentifyUI: trackUI, SecretUI: u2.NewSecretUI()}
   737  	eng = NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   738  	m = libkb.NewMetaContextForTest(tc).WithUIs(uis)
   739  	err = engine.RunEngine2(m, eng)
   740  	require.NoError(t, err)
   741  
   742  	fDHKeys := eng.GetPublicKIDs()
   743  	if len(fDHKeys) != 1 { // We requested Entity Keys only, so no PUKs or Device Keys (except for the sender's own key)
   744  		t.Errorf("number of DH keys found: %d, expected 1", len(fDHKeys))
   745  	}
   746  	fDHKeyset := make(map[keybase1.KID]struct{})
   747  	for _, fPUK := range fDHKeys {
   748  		fDHKeyset[fPUK] = struct{}{}
   749  	}
   750  
   751  	u2PUK := u2.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   752  	if _, ok := fDHKeyset[u2PUK]; !ok {
   753  		t.Errorf("expected to find key %v, which was not retrieved", u2PUK)
   754  	}
   755  
   756  	symKeys := eng.GetSymmetricKeys()
   757  	if len(symKeys) != 1 {
   758  		t.Errorf("number of symmetric keys found: %d, expected 1", len(symKeys))
   759  	}
   760  
   761  	team, err := teams.Load(m.Ctx(), m.G(), keybase1.LoadTeamArg{Name: teamName})
   762  	require.NoError(t, err)
   763  	teamSaltpackKey, err := team.SaltpackEncryptionKeyLatest(m.Ctx())
   764  	require.NoError(t, err)
   765  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
   766  
   767  	// Now we look for keys for a team, without including the sender's keys
   768  	arg = libkb.SaltpackRecipientKeyfinderArg{
   769  		TeamRecipients: []string{teamName},
   770  		UseEntityKeys:  true,
   771  		NoSelfEncrypt:  true,
   772  	}
   773  	eng = NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   774  	err = engine.RunEngine2(m, eng)
   775  	require.NoError(t, err)
   776  
   777  	fDHKeys = eng.GetPublicKIDs()
   778  	if len(fDHKeys) != 0 {
   779  		t.Errorf("number of DH keys found: %d, expected 0", len(fDHKeys))
   780  	}
   781  
   782  	symKeys = eng.GetSymmetricKeys()
   783  	if len(symKeys) != 1 {
   784  		t.Errorf("number of symmetric keys found: %d, expected 1", len(symKeys))
   785  	}
   786  
   787  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
   788  
   789  	// Now we look for keys for a team, including the device keys of the members
   790  	arg = libkb.SaltpackRecipientKeyfinderArg{
   791  		TeamRecipients: []string{teamName},
   792  		UseEntityKeys:  true,
   793  		UseDeviceKeys:  true,
   794  	}
   795  	eng = NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   796  	err = engine.RunEngine2(m, eng)
   797  	require.NoError(t, err)
   798  
   799  	fDHKeys = eng.GetPublicKIDs()
   800  	if len(fDHKeys) != 3 { // 1 device key for u1, 1 device key + 1 puk for u2 (as he is the sender).
   801  		t.Errorf("number of DH keys found: %d, expected 3", len(fDHKeys))
   802  	}
   803  	fDHKeyset = make(map[keybase1.KID]struct{})
   804  	for _, fPUK := range fDHKeys {
   805  		fDHKeyset[fPUK] = struct{}{}
   806  	}
   807  
   808  	if _, ok := fDHKeyset[u2PUK]; !ok {
   809  		t.Errorf("expected to find key %v, which was not retrieved", u2PUK)
   810  	}
   811  	key, err := u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u1.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   812  	require.NoError(t, err)
   813  	KID := key.GetKID()
   814  	if _, ok := fDHKeyset[KID]; !ok {
   815  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   816  	}
   817  	key, err = u2.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u2.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   818  	require.NoError(t, err)
   819  	KID = key.GetKID()
   820  	if _, ok := fDHKeyset[KID]; !ok {
   821  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   822  	}
   823  
   824  	symKeys = eng.GetSymmetricKeys()
   825  	if len(symKeys) != 1 {
   826  		t.Errorf("number of symmetric keys found: %d, expected 1", len(symKeys))
   827  	}
   828  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
   829  
   830  }
   831  
   832  func TestSaltpackRecipientKeyfinderTeamWithDeletedUser(t *testing.T) {
   833  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   834  	defer tc.Cleanup()
   835  
   836  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   837  	require.NoError(t, err)
   838  	u2, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   839  	require.NoError(t, err)
   840  
   841  	_, teamName := createTeam(tc)
   842  	_, err = teams.AddMember(context.TODO(), tc.G, teamName, u1.Username, keybase1.TeamRole_WRITER, nil)
   843  	require.NoError(t, err)
   844  
   845  	// u2 is part of the team, keyfinding should succeed.
   846  	// We look for keys for the team, including the device keys of the members
   847  	trackUI := &kbtest.FakeIdentifyUI{
   848  		Proofs: make(map[string]string),
   849  	}
   850  	uis := libkb.UIs{IdentifyUI: trackUI, SecretUI: u2.NewSecretUI()}
   851  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   852  	arg := libkb.SaltpackRecipientKeyfinderArg{
   853  		TeamRecipients: []string{teamName},
   854  		UseEntityKeys:  true,
   855  		UseDeviceKeys:  true,
   856  	}
   857  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   858  	err = engine.RunEngine2(m, eng)
   859  	require.NoError(t, err)
   860  
   861  	fDHKeys := eng.GetPublicKIDs()
   862  	if len(fDHKeys) != 3 { // 1 device key for u1, 1 device key + 1 puk for u2 (as he is the sender).
   863  		t.Errorf("number of DH keys found: %d, expected 3", len(fDHKeys))
   864  	}
   865  	fDHKeyset := make(map[keybase1.KID]struct{})
   866  	for _, fPUK := range fDHKeys {
   867  		fDHKeyset[fPUK] = struct{}{}
   868  	}
   869  
   870  	u2PUK := u2.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   871  	if _, ok := fDHKeyset[u2PUK]; !ok {
   872  		t.Errorf("expected to find key %v, which was not retrieved", u2PUK)
   873  	}
   874  
   875  	key, err := u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u1.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   876  	require.NoError(t, err)
   877  	KID := key.GetKID()
   878  	if _, ok := fDHKeyset[KID]; !ok {
   879  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   880  	}
   881  	key, err = u2.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u2.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   882  	require.NoError(t, err)
   883  	KID = key.GetKID()
   884  	if _, ok := fDHKeyset[KID]; !ok {
   885  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   886  	}
   887  
   888  	symKeys := eng.GetSymmetricKeys()
   889  
   890  	team, err := teams.Load(m.Ctx(), m.G(), keybase1.LoadTeamArg{Name: teamName})
   891  	require.NoError(t, err)
   892  	teamSaltpackKey, err := team.SaltpackEncryptionKeyLatest(m.Ctx())
   893  	require.NoError(t, err)
   894  
   895  	if len(symKeys) != 1 {
   896  		t.Errorf("number of symmetric keys found: %d, expected 1", len(symKeys))
   897  	}
   898  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
   899  
   900  	// Now we delete user u2, and we check that u1 is still able to find keys for the team (which do not include keys for u2).
   901  	kbtest.DeleteAccount(tc, u2)
   902  
   903  	err = u1.Login(tc.G)
   904  	require.NoError(t, err)
   905  	uis = libkb.UIs{IdentifyUI: trackUI, SecretUI: u1.NewSecretUI()}
   906  	m = libkb.NewMetaContextForTest(tc).WithUIs(uis)
   907  	arg = libkb.SaltpackRecipientKeyfinderArg{
   908  		TeamRecipients: []string{teamName},
   909  		UseEntityKeys:  true,
   910  		UseDeviceKeys:  true,
   911  	}
   912  	eng = NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   913  	err = engine.RunEngine2(m, eng)
   914  	require.NoError(t, err)
   915  
   916  	fDHKeys = eng.GetPublicKIDs()
   917  	if len(fDHKeys) != 2 { // 1 device key + 1 puk for u1 (as he is the sender and the only member of the team).
   918  		t.Errorf("number of DH keys found: %d, expected 3", len(fDHKeys))
   919  	}
   920  	fDHKeyset = make(map[keybase1.KID]struct{})
   921  	for _, fPUK := range fDHKeys {
   922  		fDHKeyset[fPUK] = struct{}{}
   923  	}
   924  
   925  	u1PUK := u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   926  	if _, ok := fDHKeyset[u1PUK]; !ok {
   927  		t.Errorf("expected to find key %v, which was not retrieved", u2PUK)
   928  	}
   929  
   930  	key, err = u1.User.GetComputedKeyFamily().GetEncryptionSubkeyForDevice(u1.User.GetComputedKeyFamily().GetAllActiveDevices()[0].ID)
   931  	require.NoError(t, err)
   932  	KID = key.GetKID()
   933  	if _, ok := fDHKeyset[KID]; !ok {
   934  		t.Errorf("expected to find key %v, which was not retrieved", KID)
   935  	}
   936  
   937  	symKeys = eng.GetSymmetricKeys()
   938  
   939  	if len(symKeys) != 1 {
   940  		t.Errorf("number of symmetric keys found: %d, expected 1", len(symKeys))
   941  	}
   942  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
   943  }
   944  
   945  func TestSaltpackRecipientKeyfinderImplicitTeam(t *testing.T) {
   946  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
   947  	defer tc.Cleanup()
   948  
   949  	teams.ServiceInit(tc.G)
   950  
   951  	// First, try to get keys for a non existing user assertion without logging in, which should fail
   952  	b, err := libkb.RandBytes(4)
   953  	require.NoError(tc.T, err)
   954  	nonExistingUserAssertion := "u_" + hex.EncodeToString(b) + "@rooter"
   955  
   956  	trackUI := &kbtest.FakeIdentifyUI{
   957  		Proofs: make(map[string]string),
   958  	}
   959  
   960  	uis := libkb.UIs{IdentifyUI: trackUI}
   961  	arg := libkb.SaltpackRecipientKeyfinderArg{
   962  		Recipients:    []string{nonExistingUserAssertion},
   963  		UseEntityKeys: true,
   964  		NoSelfEncrypt: true,
   965  	}
   966  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   967  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
   968  	err = engine.RunEngine2(m, eng) // Should fail
   969  	if _, ok := err.(libkb.RecipientNotFoundError); !ok {
   970  		t.Fatalf("expected error type libkb.RecipientNotFoundError, got %T (%s)", err, err)
   971  	}
   972  
   973  	// Now, retry with a valid user logged in, which should succeed
   974  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
   975  	require.NoError(t, err)
   976  	err = u1.Login(tc.G)
   977  	require.NoError(t, err)
   978  
   979  	uis = libkb.UIs{IdentifyUI: trackUI, SecretUI: u1.NewSecretUI()}
   980  	arg = libkb.SaltpackRecipientKeyfinderArg{
   981  		Recipients:    []string{nonExistingUserAssertion},
   982  		UseEntityKeys: true,
   983  	}
   984  	eng = NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
   985  	m = libkb.NewMetaContextForTest(tc).WithUIs(uis)
   986  	err = engine.RunEngine2(m, eng)
   987  	require.NoError(t, err)
   988  
   989  	fDHKeys := eng.GetPublicKIDs()
   990  	if len(fDHKeys) != 1 { // This is the sender's own PUK
   991  		t.Errorf("number of DH keys found: %d, expected 1", len(fDHKeys))
   992  	}
   993  	fDHKeyset := make(map[keybase1.KID]struct{})
   994  	for _, fPUK := range fDHKeys {
   995  		fDHKeyset[fPUK] = struct{}{}
   996  	}
   997  
   998  	u1PUK := u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
   999  	if _, ok := fDHKeyset[u1PUK]; !ok {
  1000  		t.Errorf("expected to find key %v, which was not retrieved", u1PUK)
  1001  	}
  1002  
  1003  	symKeys := eng.GetSymmetricKeys()
  1004  	if len(symKeys) != 1 {
  1005  		t.Errorf("number of symmetric keys found: %d, expected 1", len(symKeys))
  1006  	}
  1007  
  1008  	team, _, _, err := teams.LookupImplicitTeam(m.Ctx(), m.G(), u1.Username+","+nonExistingUserAssertion, false, teams.ImplicitTeamOptions{})
  1009  	require.NoError(t, err)
  1010  	teamSaltpackKey, err := team.SaltpackEncryptionKeyLatest(m.Ctx())
  1011  	require.NoError(t, err)
  1012  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
  1013  }
  1014  
  1015  func TestSaltpackRecipientKeyfinderImplicitTeamNoSelfEncrypt(t *testing.T) {
  1016  	tc := SetupKeyfinderEngineTest(t, "SaltpackRecipientKeyfinderEngine")
  1017  	defer tc.Cleanup()
  1018  
  1019  	teams.ServiceInit(tc.G)
  1020  
  1021  	// First, try to get keys for a non existing user assertion with NoSelfEncrypt, which should fail
  1022  	u1, err := kbtest.CreateAndSignupFakeUser("spkfe", tc.G)
  1023  	require.NoError(t, err)
  1024  	err = u1.Login(tc.G)
  1025  	require.NoError(t, err)
  1026  
  1027  	b, err := libkb.RandBytes(4)
  1028  	require.NoError(tc.T, err)
  1029  	nonExistingUserAssertion := "u_" + hex.EncodeToString(b) + "@rooter"
  1030  
  1031  	trackUI := &kbtest.FakeIdentifyUI{
  1032  		Proofs: make(map[string]string),
  1033  	}
  1034  
  1035  	uis := libkb.UIs{IdentifyUI: trackUI}
  1036  	arg := libkb.SaltpackRecipientKeyfinderArg{
  1037  		Recipients:    []string{nonExistingUserAssertion},
  1038  		UseEntityKeys: true,
  1039  		NoSelfEncrypt: true,
  1040  	}
  1041  	eng := NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
  1042  	m := libkb.NewMetaContextForTest(tc).WithUIs(uis)
  1043  	err = engine.RunEngine2(m, eng) // Should fail
  1044  	if _, ok := err.(libkb.RecipientNotFoundError); !ok {
  1045  		t.Fatalf("expected error type libkb.RecipientNotFoundError, got %T (%s)", err, err)
  1046  	}
  1047  
  1048  	// Now, try again without NoSelfEncrypt, which should succeed
  1049  	arg = libkb.SaltpackRecipientKeyfinderArg{
  1050  		Recipients:    []string{nonExistingUserAssertion},
  1051  		UseEntityKeys: true,
  1052  	}
  1053  	eng = NewSaltpackRecipientKeyfinderEngineAsInterface(arg)
  1054  	m = libkb.NewMetaContextForTest(tc).WithUIs(uis)
  1055  	err = engine.RunEngine2(m, eng)
  1056  	require.NoError(t, err)
  1057  
  1058  	fDHKeys := eng.GetPublicKIDs()
  1059  	if len(fDHKeys) != 1 { // This is the sender's own PUK
  1060  		t.Errorf("number of DH keys found: %d, expected 1", len(fDHKeys))
  1061  	}
  1062  	fDHKeyset := make(map[keybase1.KID]struct{})
  1063  	for _, fPUK := range fDHKeys {
  1064  		fDHKeyset[fPUK] = struct{}{}
  1065  	}
  1066  
  1067  	u1PUK := u1.User.GetComputedKeyFamily().GetLatestPerUserKey().EncKID
  1068  	if _, ok := fDHKeyset[u1PUK]; !ok {
  1069  		t.Errorf("expected to find key %v, which was not retrieved", u1PUK)
  1070  	}
  1071  
  1072  	symKeys := eng.GetSymmetricKeys()
  1073  	if len(symKeys) != 1 {
  1074  		t.Errorf("number of symmetric keys found: %d, expected 1", len(symKeys))
  1075  	}
  1076  
  1077  	team, _, _, err := teams.LookupImplicitTeam(m.Ctx(), m.G(), u1.Username+","+nonExistingUserAssertion, false, teams.ImplicitTeamOptions{})
  1078  	require.NoError(t, err)
  1079  	teamSaltpackKey, err := team.SaltpackEncryptionKeyLatest(m.Ctx())
  1080  	require.NoError(t, err)
  1081  	require.True(t, bytes.Equal(teamSaltpackKey.Key[:], symKeys[0].Key[:]))
  1082  }