1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package engine
5
6import (
7	"context"
8	"testing"
9	"time"
10
11	"github.com/keybase/client/go/libkb"
12	keybase1 "github.com/keybase/client/go/protocol/keybase1"
13	"github.com/keybase/clockwork"
14	"github.com/stretchr/testify/require"
15)
16
17func TestLoadUserPlusKeysHasKeys(t *testing.T) {
18	tc := SetupEngineTest(t, "user")
19	defer tc.Cleanup()
20
21	CreateAndSignupFakeUserPaper(tc, "login")
22	me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G))
23	if err != nil {
24		t.Fatal(err)
25	}
26	up, err := libkb.LoadUserPlusKeys(context.TODO(), tc.G, me.GetUID(), "")
27	if err != nil {
28		t.Fatal(err)
29	}
30	if len(up.DeviceKeys) != 4 {
31		t.Errorf("num device keys: %d, expected 4", len(up.DeviceKeys))
32	}
33}
34
35func TestLoadUserPlusKeysRevoked(t *testing.T) {
36	fakeClock := clockwork.NewFakeClockAt(time.Now())
37	tc := SetupEngineTest(t, "login")
38	defer tc.Cleanup()
39	tc.G.SetClock(fakeClock)
40
41	fu := CreateAndSignupFakeUserPaper(tc, "login")
42	me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G))
43	if err != nil {
44		t.Fatal(err)
45	}
46	up, err := libkb.LoadUserPlusKeys(context.TODO(), tc.G, me.GetUID(), "")
47	if err != nil {
48		t.Fatal(err)
49	}
50
51	if len(up.DeviceKeys) != 4 {
52		t.Errorf("device keys: %d, expected 4", len(up.DeviceKeys))
53	}
54	if len(up.RevokedDeviceKeys) != 0 {
55		t.Errorf("revoked keys: %d, expected 0", len(up.RevokedDeviceKeys))
56	}
57
58	devices, _ := getActiveDevicesAndKeys(tc, fu)
59	var paper *libkb.Device
60	for _, device := range devices {
61		if device.Type == keybase1.DeviceTypeV2_PAPER {
62			paper = device.Device
63			break
64		}
65	}
66
67	if err := doRevokeDevice(tc, fu, paper.ID, false, false); err != nil {
68		t.Fatal(err)
69	}
70	fakeClock.Advance(libkb.CachedUserTimeout + 2*time.Second)
71
72	up2, err := libkb.LoadUserPlusKeys(context.TODO(), tc.G, me.GetUID(), "")
73	if err != nil {
74		t.Fatal(err)
75	}
76
77	if len(up2.DeviceKeys) != 2 {
78		t.Errorf("device keys: %d, expected 2", len(up2.DeviceKeys))
79	}
80	if len(up2.RevokedDeviceKeys) != 2 {
81		t.Errorf("revoked keys: %d, expected 2", len(up2.RevokedDeviceKeys))
82	}
83}
84
85// TestMerkleHashMetaAndFirstAppearedInKeyFamily tests new user & key family features:
86//   * FirstAppearedMerkleSeqnoUnverified in sig chain links
87//   * EldestSeqno in sig chain links
88//   * HashMeta in sig chain links
89// We should be able to see these fields in sigchains and also propagated through
90// to the KeyFamilies
91func TestMerkleHashMetaAndFirstAppearedInKeyFamily(t *testing.T) {
92	tc := SetupEngineTest(t, "login")
93	defer tc.Cleanup()
94	CreateAndSignupFakeUser(tc, "login")
95	me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G))
96	require.NoError(t, err)
97
98	ckf := me.GetComputedKeyFamily()
99	checkKey := func(key libkb.GenericKey, cki libkb.ComputedKeyInfo, err error) {
100		require.NoError(t, err)
101		require.NotNil(t, key, "non-nil key")
102		require.Equal(t, len(cki.DelegatedAtHashMeta), 32, "needed a SHA256 hash for merkle hash_meta")
103		require.True(t, (cki.FirstAppearedUnverified > 0), "need a >0 merkle root first appeared in")
104	}
105	checkSibkey := func(kid keybase1.KID) {
106		checkKey(ckf.FindActiveSibkey(kid))
107	}
108	checkSubkey := func(kid keybase1.KID) {
109		checkKey(ckf.FindActiveEncryptionSubkey(kid))
110	}
111
112	for _, sibkey := range ckf.GetAllActiveSibkeys() {
113		checkSibkey(sibkey.GetKID())
114	}
115	for _, subkey := range ckf.GetAllActiveSubkeys() {
116		checkSubkey(subkey.GetKID())
117	}
118}
119
120func assertPostedHighSkipSeqno(t *testing.T, tc libkb.TestContext, name string, seqno int) {
121	u, err := libkb.LoadUser(libkb.NewLoadUserByNameArg(tc.G, name))
122	if err != nil {
123		t.Fatal(err)
124	}
125
126	highSkip := u.GetLastLink().GetHighSkip()
127	require.Equal(t, highSkip.Seqno, keybase1.Seqno(seqno))
128}
129
130func TestBlankUserHighSkip(t *testing.T) {
131	tc := SetupEngineTest(t, "user")
132	defer tc.Cleanup()
133
134	i := CreateAndSignupFakeUser(tc, "login")
135
136	assertPostedHighSkipSeqno(t, tc, i.Username, 1)
137}
138
139func TestPaperUserHighSkip(t *testing.T) {
140	tc := SetupEngineTest(t, "user")
141	defer tc.Cleanup()
142	them, _ := createFakeUserWithNoKeys(tc)
143
144	i := CreateAndSignupFakeUserPaper(tc, "login")
145	assertPostedHighSkipSeqno(t, tc, i.Username, 4)
146
147	trackUser(tc, i, libkb.NewNormalizedUsername(them), libkb.GetDefaultSigVersion(tc.G))
148	assertPostedHighSkipSeqno(t, tc, i.Username, 4)
149
150	eng := NewPaperKey(tc.G)
151	uis := libkb.UIs{
152		LogUI:    tc.G.UI.GetLogUI(),
153		LoginUI:  &libkb.TestLoginUI{},
154		SecretUI: &libkb.TestSecretUI{},
155	}
156	m := NewMetaContextForTest(tc).WithUIs(uis)
157	if err := RunEngine2(m, eng); err != nil {
158		t.Fatal(err)
159	}
160	assertPostedHighSkipSeqno(t, tc, i.Username, 7)
161}
162