Beispiel #1
0
// Test that canceling a signing RPC returns the correct error
func TestCryptoClientDecryptTLFCryptKeyClientHalfCanceled(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	ctlChan := make(chan struct{})
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, ctlChan)
	c := newCryptoClientWithClient(config.Codec(), cancelableClient{fc}, logger.NewTestLogger(t))

	_, _, ephPublicKey, ephPrivateKey, cryptKey, err := c.MakeRandomTLFKeys()
	if err != nil {
		t.Fatal(err)
	}

	serverHalf, err := c.MakeRandomTLFCryptKeyServerHalf()
	if err != nil {
		t.Fatal(err)
	}

	clientHalf, err := c.MaskTLFCryptKey(serverHalf, cryptKey)
	if err != nil {
		t.Fatal(err)
	}

	encryptedClientHalf, err := c.EncryptTLFCryptKeyClientHalf(ephPrivateKey, cryptPrivateKey.getPublicKey(), clientHalf)
	if err != nil {
		t.Fatal(err)
	}

	f := func(ctx context.Context) error {
		_, err = c.DecryptTLFCryptKeyClientHalf(ctx, ephPublicKey,
			encryptedClientHalf)
		return err
	}
	testWithCanceledContext(t, context.Background(), ctlChan, ctlChan, f)
}
Beispiel #2
0
func NewConfigMock(c *gomock.Controller, ctr *SafeTestReporter) *ConfigMock {
	config := &ConfigMock{}
	config.mockKbfs = NewMockKBFSOps(c)
	config.SetKBFSOps(config.mockKbfs)
	config.mockKbpki = NewMockKBPKI(c)
	config.SetKBPKI(config.mockKbpki)
	config.mockKeyman = NewMockKeyManager(c)
	config.SetKeyManager(config.mockKeyman)
	config.mockRep = NewMockReporter(c)
	config.SetReporter(config.mockRep)
	config.mockMdcache = NewMockMDCache(c)
	config.SetMDCache(config.mockMdcache)
	config.mockKcache = NewMockKeyCache(c)
	config.SetKeyCache(config.mockKcache)
	config.mockBcache = NewMockBlockCache(c)
	config.SetBlockCache(config.mockBcache)
	config.mockCrypto = NewMockCrypto(c)
	config.SetCrypto(config.mockCrypto)
	config.mockCodec = NewMockCodec(c)
	config.mockCodec.EXPECT().RegisterType(gomock.Any(), gomock.Any()).
		AnyTimes().Return()
	config.mockCodec.EXPECT().RegisterIfaceSliceType(gomock.Any(),
		gomock.Any(), gomock.Any()).AnyTimes().Return()
	config.SetCodec(config.mockCodec)
	config.mockMdops = NewMockMDOps(c)
	config.SetMDOps(config.mockMdops)
	config.mockKops = NewMockKeyOps(c)
	config.SetKeyOps(config.mockKops)
	config.mockBops = NewMockBlockOps(c)
	config.SetBlockOps(config.mockBops)
	config.mockMdserv = NewMockMDServer(c)
	config.SetMDServer(config.mockMdserv)
	config.mockKserv = NewMockKeyServer(c)
	config.SetKeyServer(config.mockKserv)
	config.mockBserv = NewMockBlockServer(c)
	config.SetBlockServer(config.mockBserv)
	config.mockBsplit = NewMockBlockSplitter(c)
	config.SetBlockSplitter(config.mockBsplit)
	config.mockNotifier = NewMockNotifier(c)
	config.SetNotifier(config.mockNotifier)
	config.mockClock = NewMockClock(c)
	config.SetClock(config.mockClock)
	config.mockRekeyQueue = NewMockRekeyQueue(c)
	config.SetRekeyQueue(config.mockRekeyQueue)
	config.observer = &FakeObserver{}
	config.ctr = ctr
	config.SetLoggerMaker(func(m string) logger.Logger {
		return logger.NewTestLogger(ctr.t)
	})
	// turn off background flushing by default during tests
	config.noBGFlush = true

	config.maxFileBytes = maxFileBytesDefault
	config.maxNameBytes = maxNameBytesDefault
	config.maxDirBytes = maxDirBytesDefault

	return config
}
func newKeybaseDaemonRPCWithFakeClient(t *testing.T) (
	*KeybaseDaemonRPC, chan struct{}) {
	ctlChan := make(chan struct{})
	c := newKeybaseDaemonRPCWithClient(
		nil,
		cancelableClient{blockingClient{ctlChan}},
		logger.NewTestLogger(t))
	return c, ctlChan
}
Beispiel #4
0
// Test that when decrypting set of client keys, the first working one
// is used to decrypt.
func TestCryptoClientDecryptEncryptedTLFCryptKeyClientHalfAny(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil)
	c := newCryptoClientWithClient(config.Codec(), fc, logger.NewTestLogger(t))

	keys := make([]EncryptedTLFCryptKeyClientAndEphemeral, 0, 4)
	clientHalves := make([]TLFCryptKeyClientHalf, 0, 4)
	for i := 0; i < 4; i++ {
		_, _, ephPublicKey, ephPrivateKey, cryptKey, err := c.MakeRandomTLFKeys()
		if err != nil {
			t.Fatal(err)
		}

		serverHalf, err := c.MakeRandomTLFCryptKeyServerHalf()
		if err != nil {
			t.Fatal(err)
		}

		clientHalf, err := c.MaskTLFCryptKey(serverHalf, cryptKey)
		if err != nil {
			t.Fatal(err)
		}

		// See crypto_common_test.go for tests that this actually
		// performs encryption.
		encryptedClientHalf, err := c.EncryptTLFCryptKeyClientHalf(ephPrivateKey, cryptPrivateKey.getPublicKey(), clientHalf)
		if err != nil {
			t.Fatal(err)
		}

		if encryptedClientHalf.Version != EncryptionSecretbox {
			t.Fatalf("Unexpected encryption version %d", encryptedClientHalf.Version)
		}
		keys = append(keys, EncryptedTLFCryptKeyClientAndEphemeral{
			PubKey:     cryptPrivateKey.getPublicKey(),
			ClientHalf: encryptedClientHalf,
			EPubKey:    ephPublicKey,
		})
		clientHalves = append(clientHalves, clientHalf)
	}

	decryptedClientHalf, index, err := c.DecryptTLFCryptKeyClientHalfAny(
		context.Background(), keys)
	if err != nil {
		t.Fatal(err)
	}

	if index != 0 {
		t.Errorf("expected first key to work. Actual key index: %d", index)
	}

	if clientHalves[0] != decryptedClientHalf {
		t.Error("clientHalf != decryptedClientHalf")
	}
}
Beispiel #5
0
// Test that decrypting an TLF crypt key client half encrypted with
// box.Seal works.
func TestCryptoClientDecryptTLFCryptKeyClientHalfBoxSeal(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil)
	c := newCryptoClientWithClient(config.Codec(), fc, logger.NewTestLogger(t))

	_, _, ephPublicKey, ephPrivateKey, cryptKey, err := c.MakeRandomTLFKeys()
	if err != nil {
		t.Fatal(err)
	}

	serverHalf, err := c.MakeRandomTLFCryptKeyServerHalf()
	if err != nil {
		t.Fatal(err)
	}

	clientHalf, err := c.MaskTLFCryptKey(serverHalf, cryptKey)
	if err != nil {
		t.Fatal(err)
	}

	var nonce [24]byte
	err = cryptoRandRead(nonce[:])
	if err != nil {
		t.Fatal(err)
	}

	keypair, err := libkb.ImportKeypairFromKID(cryptPrivateKey.getPublicKey().kid)
	if err != nil {
		t.Fatal(err)
	}

	dhKeyPair, ok := keypair.(libkb.NaclDHKeyPair)
	if !ok {
		t.Fatal(libkb.KeyCannotEncryptError{})
	}

	encryptedData := box.Seal(nil, clientHalf.data[:], &nonce, (*[32]byte)(&dhKeyPair.Public), (*[32]byte)(&ephPrivateKey.data))
	encryptedClientHalf := EncryptedTLFCryptKeyClientHalf{
		Version:       EncryptionSecretbox,
		Nonce:         nonce[:],
		EncryptedData: encryptedData,
	}

	decryptedClientHalf, err := c.DecryptTLFCryptKeyClientHalf(
		context.Background(), ephPublicKey, encryptedClientHalf)
	if err != nil {
		t.Fatal(err)
	}

	if clientHalf != decryptedClientHalf {
		t.Error("clientHalf != decryptedClientHalf")
	}
}
// If we cancel the RPC before the RPC returns, the call should error quickly.
func TestKeybaseDaemonRPCGetCurrentSessionCanceled(t *testing.T) {
	serverConn, conn := rpc.MakeConnectionForTest(t)
	daemon := newKeybaseDaemonRPCWithClient(
		nil,
		conn.GetClient(),
		logger.NewTestLogger(t))

	f := func(ctx context.Context) error {
		_, err := daemon.CurrentSession(ctx, 0)
		return err
	}
	testRPCWithCanceledContext(t, serverConn, f)
}
Beispiel #7
0
// Test that canceling a signing RPC returns the correct error
func TestCryptoClientSignCanceled(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	ctlChan := make(chan struct{})
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, ctlChan)
	c := newCryptoClientWithClient(config.Codec(), cancelableClient{fc}, logger.NewTestLogger(t))

	f := func(ctx context.Context) error {
		msg := []byte("message")
		_, err := c.Sign(ctx, msg)
		return err
	}
	testWithCanceledContext(t, context.Background(), ctlChan, ctlChan, f)
}
Beispiel #8
0
// Test that attempting to decrypt an empty set of client keys fails.
func TestCryptoClientDecryptEmptyEncryptedTLFCryptKeyClientHalfAny(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil)
	c := newCryptoClientWithClient(config.Codec(), fc, logger.NewTestLogger(t))

	keys := make([]EncryptedTLFCryptKeyClientAndEphemeral, 0, 0)

	_, _, err := c.DecryptTLFCryptKeyClientHalfAny(
		context.Background(), keys)
	if _, ok := err.(NoKeysError); !ok {
		t.Fatalf("expected NoKeysError. Actual error: %v", err)
	}
}
func TestKBFSOpsCancelGetFavorites(t *testing.T) {
	config, _, _ := kbfsOpsConcurInit(t, "test_user")
	defer CheckConfigAndShutdown(t, config)

	serverConn, conn := rpc.MakeConnectionForTest(t)
	daemon := newKeybaseDaemonRPCWithClient(
		nil,
		conn.GetClient(),
		logger.NewTestLogger(t))
	config.SetKeybaseDaemon(daemon)

	f := func(ctx context.Context) error {
		_, err := config.KBFSOps().GetFavorites(ctx)
		return err
	}
	testRPCWithCanceledContext(t, serverConn, f)
}
Beispiel #10
0
// Test that signing a message and then verifying it works.
func TestCryptoClientSignAndVerify(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil)
	c := newCryptoClientWithClient(config.Codec(), fc, logger.NewTestLogger(t))

	msg := []byte("message")
	sigInfo, err := c.Sign(context.Background(), msg)
	if err != nil {
		t.Fatal(err)
	}

	err = c.Verify(msg, sigInfo)
	if err != nil {
		t.Error(err)
	}
}
Beispiel #11
0
// Test that decrypting a TLF crypt key client half encrypted with the
// default method (currently nacl/box) works.
func TestCryptoClientDecryptEncryptedTLFCryptKeyClientHalf(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil)
	c := newCryptoClientWithClient(config.Codec(), fc, logger.NewTestLogger(t))

	_, _, ephPublicKey, ephPrivateKey, cryptKey, err := c.MakeRandomTLFKeys()
	if err != nil {
		t.Fatal(err)
	}

	serverHalf, err := c.MakeRandomTLFCryptKeyServerHalf()
	if err != nil {
		t.Fatal(err)
	}

	clientHalf, err := c.MaskTLFCryptKey(serverHalf, cryptKey)
	if err != nil {
		t.Fatal(err)
	}

	// See crypto_common_test.go for tests that this actually
	// performs encryption.
	encryptedClientHalf, err := c.EncryptTLFCryptKeyClientHalf(ephPrivateKey, cryptPrivateKey.getPublicKey(), clientHalf)
	if err != nil {
		t.Fatal(err)
	}

	if encryptedClientHalf.Version != EncryptionSecretbox {
		t.Fatalf("Unexpected encryption version %d", encryptedClientHalf.Version)
	}

	decryptedClientHalf, err := c.DecryptTLFCryptKeyClientHalf(
		context.Background(), ephPublicKey, encryptedClientHalf)
	if err != nil {
		t.Fatal(err)
	}

	if clientHalf != decryptedClientHalf {
		t.Error("clientHalf != decryptedClientHalf")
	}
}
// Test that the session cache works and is invalidated as expected.
func TestKeybaseDaemonSessionCache(t *testing.T) {
	k := MakeLocalUserCryptPublicKeyOrBust(
		libkb.NormalizedUsername("fake username"))
	v := MakeLocalUserVerifyingKeyOrBust(
		libkb.NormalizedUsername("fake username"))
	session := SessionInfo{
		UID:            keybase1.UID("fake uid"),
		Token:          "fake token",
		CryptPublicKey: k,
		VerifyingKey:   v,
	}

	client := &fakeKeybaseClient{session: session}
	c := newKeybaseDaemonRPCWithClient(
		nil, client, logger.NewTestLogger(t))

	// Should fill cache.
	testCurrentSession(t, client, c, session, expectCall)

	// Should be cached.
	testCurrentSession(t, client, c, session, expectCached)

	// Should invalidate cache.
	err := c.LoggedOut(context.Background())
	if err != nil {
		t.Fatal(err)
	}

	// Should fill cache again.
	testCurrentSession(t, client, c, session, expectCall)

	// Should be cached again.
	testCurrentSession(t, client, c, session, expectCached)

	// Should invalidate cache.
	c.OnDisconnected(UsingExistingConnection)

	// Should fill cache again.
	testCurrentSession(t, client, c, session, expectCall)
}
// Test that the user cache works and is invalidated as expected.
func TestKeybaseDaemonUserCache(t *testing.T) {
	uid1 := keybase1.UID("uid1")
	uid2 := keybase1.UID("uid2")
	name1 := libkb.NewNormalizedUsername("name1")
	name2 := libkb.NewNormalizedUsername("name2")
	users := map[keybase1.UID]UserInfo{
		uid1: {Name: name1},
		uid2: {Name: name2},
	}
	client := &fakeKeybaseClient{users: users}
	c := newKeybaseDaemonRPCWithClient(
		nil, client, logger.NewTestLogger(t))

	// Should fill cache.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should fill cache.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should not be cached.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should invalidate cache for uid1.
	err := c.UserChanged(context.Background(), uid1)
	require.NoError(t, err)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should still be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for uid2.
	err = c.UserChanged(context.Background(), uid2)
	require.NoError(t, err)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for all users.
	c.OnDisconnected(context.Background(), rpc.UsingExistingConnection)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)

	// Test that CheckForRekey gets called only if the logged-in user
	// changes.
	session := SessionInfo{
		UID: uid1,
	}
	c.setCachedCurrentSession(session)
	ctr := NewSafeTestReporter(t)
	mockCtrl := gomock.NewController(ctr)
	config := NewConfigMock(mockCtrl, ctr)
	c.config = config
	defer func() {
		config.ctr.CheckForFailures()
		mockCtrl.Finish()
	}()
	errChan := make(chan error, 1)
	config.mockMdserv.EXPECT().CheckForRekeys(gomock.Any()).Do(
		func(ctx context.Context) {
			errChan <- nil
		}).Return(errChan)
	err = c.UserChanged(context.Background(), uid1)
	<-errChan
	// This one shouldn't trigger CheckForRekeys; if it does, the mock
	// controller will catch it during Finish.
	err = c.UserChanged(context.Background(), uid2)
}
Beispiel #14
0
func setTestLogger(config Config, t logger.TestLogBackend) {
	config.SetLoggerMaker(func(m string) logger.Logger {
		return logger.NewTestLogger(t)
	})
}
Beispiel #15
0
// Test various failure cases for DecryptTLFCryptKeyClientHalf.
func TestCryptoClientDecryptTLFCryptKeyClientHalfFailures(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil)
	c := newCryptoClientWithClient(config.Codec(), fc, logger.NewTestLogger(t))

	_, _, ephPublicKey, ephPrivateKey, cryptKey, err := c.MakeRandomTLFKeys()
	if err != nil {
		t.Fatal(err)
	}

	serverHalf, err := c.MakeRandomTLFCryptKeyServerHalf()
	if err != nil {
		t.Fatal(err)
	}

	clientHalf, err := c.MaskTLFCryptKey(serverHalf, cryptKey)
	if err != nil {
		t.Fatal(err)
	}

	encryptedClientHalf, err := c.EncryptTLFCryptKeyClientHalf(ephPrivateKey, cryptPrivateKey.getPublicKey(), clientHalf)
	if err != nil {
		t.Fatal(err)
	}

	var expectedErr error

	// Wrong version.

	encryptedClientHalfWrongVersion := encryptedClientHalf
	encryptedClientHalfWrongVersion.Version++
	expectedErr = UnknownEncryptionVer{encryptedClientHalfWrongVersion.Version}
	ctx := context.Background()
	_, err = c.DecryptTLFCryptKeyClientHalf(ctx, ephPublicKey,
		encryptedClientHalfWrongVersion)
	if err != expectedErr {
		t.Errorf("Expected %v, got %v", expectedErr, err)
	}

	// Wrong sizes.

	encryptedClientHalfWrongSize := encryptedClientHalf
	encryptedClientHalfWrongSize.EncryptedData = encryptedClientHalfWrongSize.EncryptedData[:len(encryptedClientHalfWrongSize.EncryptedData)-1]
	expectedErr = libkb.DecryptionError{}
	_, err = c.DecryptTLFCryptKeyClientHalf(ctx, ephPublicKey,
		encryptedClientHalfWrongSize)
	if err != expectedErr {
		t.Errorf("Expected %v, got %v", expectedErr, err)
	}

	encryptedClientHalfWrongNonceSize := encryptedClientHalf
	encryptedClientHalfWrongNonceSize.Nonce = encryptedClientHalfWrongNonceSize.Nonce[:len(encryptedClientHalfWrongNonceSize.Nonce)-1]
	expectedErr = InvalidNonceError{encryptedClientHalfWrongNonceSize.Nonce}
	_, err = c.DecryptTLFCryptKeyClientHalf(ctx, ephPublicKey,
		encryptedClientHalfWrongNonceSize)
	if err.Error() != expectedErr.Error() {
		t.Errorf("Expected %v, got %v", expectedErr, err)
	}

	// Corrupt key.

	ephPublicKeyCorrupt := ephPublicKey
	ephPublicKeyCorrupt.data[0] = ^ephPublicKeyCorrupt.data[0]
	expectedErr = libkb.DecryptionError{}
	_, err = c.DecryptTLFCryptKeyClientHalf(ctx, ephPublicKeyCorrupt,
		encryptedClientHalf)
	if err != expectedErr {
		t.Errorf("Expected %v, got %v", expectedErr, err)
	}

	// Corrupt data.

	encryptedClientHalfCorruptData := encryptedClientHalf
	encryptedClientHalfCorruptData.EncryptedData[0] = ^encryptedClientHalfCorruptData.EncryptedData[0]
	expectedErr = libkb.DecryptionError{}
	_, err = c.DecryptTLFCryptKeyClientHalf(ctx, ephPublicKey,
		encryptedClientHalfCorruptData)
	if err != expectedErr {
		t.Errorf("Expected %v, got %v", expectedErr, err)
	}
}
Beispiel #16
0
// Test various failure cases for DecryptTLFCryptKeyClientHalfAny and that
// if a working key is present, the decryption succeeds.
func TestCryptoClientDecryptTLFCryptKeyClientHalfAnyFailures(t *testing.T) {
	signingKey := MakeFakeSigningKeyOrBust("client sign")
	cryptPrivateKey := MakeFakeCryptPrivateKeyOrBust("client crypt private")
	config := testCryptoClientConfig(t)
	fc := NewFakeCryptoClient(config, signingKey, cryptPrivateKey, nil)
	c := newCryptoClientWithClient(config.Codec(), fc, logger.NewTestLogger(t))

	_, _, ephPublicKey, ephPrivateKey, cryptKey, err := c.MakeRandomTLFKeys()
	if err != nil {
		t.Fatal(err)
	}

	serverHalf, err := c.MakeRandomTLFCryptKeyServerHalf()
	if err != nil {
		t.Fatal(err)
	}

	clientHalf, err := c.MaskTLFCryptKey(serverHalf, cryptKey)
	if err != nil {
		t.Fatal(err)
	}

	encryptedClientHalf, err := c.EncryptTLFCryptKeyClientHalf(ephPrivateKey, cryptPrivateKey.getPublicKey(), clientHalf)
	if err != nil {
		t.Fatal(err)
	}

	// Wrong version.
	encryptedClientHalfWrongVersion := encryptedClientHalf
	encryptedClientHalfWrongVersion.Version++

	// Wrong sizes.
	encryptedClientHalfWrongSize := encryptedClientHalf
	encryptedClientHalfWrongSize.EncryptedData = encryptedClientHalfWrongSize.EncryptedData[:len(encryptedClientHalfWrongSize.EncryptedData)-1]

	encryptedClientHalfWrongNonceSize := encryptedClientHalf
	encryptedClientHalfWrongNonceSize.Nonce = encryptedClientHalfWrongNonceSize.Nonce[:len(encryptedClientHalfWrongNonceSize.Nonce)-1]

	// Corrupt key.
	ephPublicKeyCorrupt := ephPublicKey
	ephPublicKeyCorrupt.data[0] = ^ephPublicKeyCorrupt.data[0]

	// Corrupt data.
	encryptedClientHalfCorruptData := encryptedClientHalf
	encryptedClientHalfCorruptData.EncryptedData = make([]byte, len(encryptedClientHalf.EncryptedData))
	copy(encryptedClientHalfCorruptData.EncryptedData, encryptedClientHalf.EncryptedData)
	encryptedClientHalfCorruptData.EncryptedData[0] = ^encryptedClientHalfCorruptData.EncryptedData[0]

	keys := []EncryptedTLFCryptKeyClientAndEphemeral{
		{
			PubKey:     cryptPrivateKey.getPublicKey(),
			ClientHalf: encryptedClientHalfWrongVersion,
			EPubKey:    ephPublicKey,
		}, {
			PubKey:     cryptPrivateKey.getPublicKey(),
			ClientHalf: encryptedClientHalfWrongSize,
			EPubKey:    ephPublicKey,
		}, {
			PubKey:     cryptPrivateKey.getPublicKey(),
			ClientHalf: encryptedClientHalfWrongNonceSize,
			EPubKey:    ephPublicKey,
		}, {
			PubKey:     cryptPrivateKey.getPublicKey(),
			ClientHalf: encryptedClientHalf,
			EPubKey:    ephPublicKeyCorrupt,
		}, {
			PubKey:     cryptPrivateKey.getPublicKey(),
			ClientHalf: encryptedClientHalfCorruptData,
			EPubKey:    ephPublicKey,
		}, {
			PubKey:     cryptPrivateKey.getPublicKey(),
			ClientHalf: encryptedClientHalf,
			EPubKey:    ephPublicKey,
		},
	}

	_, index, err := c.DecryptTLFCryptKeyClientHalfAny(
		context.Background(), keys)
	if err != nil {
		t.Fatal(err)
	}

	if index != len(keys)-1 {
		t.Errorf("expected last key to work. Actual key index: %d", index)
	}
}
// Test that the user cache works and is invalidated as expected.
func TestKeybaseDaemonUserCache(t *testing.T) {
	uid1 := keybase1.UID("uid1")
	uid2 := keybase1.UID("uid2")
	name1 := libkb.NewNormalizedUsername("name1")
	name2 := libkb.NewNormalizedUsername("name2")
	users := map[keybase1.UID]UserInfo{
		uid1: {Name: name1},
		uid2: {Name: name2},
	}
	client := &fakeKeybaseClient{users: users}
	c := newKeybaseDaemonRPCWithClient(
		nil, client, logger.NewTestLogger(t))

	// Should fill cache.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should fill cache.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should not be cached.
	testIdentify(t, client, c, uid2, name2, expectCall)

	// Should invalidate cache for uid1.
	err := c.UserChanged(context.Background(), uid1)
	if err != nil {
		t.Fatal(err)
	}

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCached)

	// Should still be cached.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for uid2.
	err = c.UserChanged(context.Background(), uid2)
	if err != nil {
		t.Fatal(err)
	}

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)

	// Should be cached again.
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCached)

	// Should invalidate cache for all users.
	c.OnDisconnected(UsingExistingConnection)

	// Should fill cache again.
	testLoadUserPlusKeys(t, client, c, uid1, name1, expectCall)
	testLoadUserPlusKeys(t, client, c, uid2, name2, expectCall)
}