1// Copyright 2017 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
10	"github.com/keybase/client/go/libkb"
11	"github.com/keybase/client/go/protocol/keybase1"
12	"github.com/stretchr/testify/require"
13)
14
15func TestPerUserKeyUpgrade(t *testing.T) {
16	tc := SetupEngineTest(t, "pukup")
17	defer tc.Cleanup()
18
19	tc.Tp.DisableUpgradePerUserKey = true
20
21	fu := CreateAndSignupFakeUserPaper(tc, "pukup")
22
23	checkPerUserKeyCount(&tc, 0)
24
25	tc.Tp.DisableUpgradePerUserKey = false
26
27	t.Logf("upgrade")
28	upgrade := func() *PerUserKeyUpgrade {
29		arg := &PerUserKeyUpgradeArgs{}
30		eng := NewPerUserKeyUpgrade(tc.G, arg)
31		uis := libkb.UIs{
32			LogUI: tc.G.UI.GetLogUI(),
33		}
34		m := NewMetaContextForTest(tc).WithUIs(uis)
35		err := RunEngine2(m, eng)
36		require.NoError(t, err)
37		return eng
38	}
39	require.True(t, upgrade().DidNewKey, "created key")
40
41	checkPerUserKeyCountLocal(&tc, 1)
42	checkPerUserKeyCount(&tc, 1)
43
44	t.Logf("revoke paper key")
45	revokeAnyPaperKey(tc, fu)
46
47	t.Logf("should be on gen 2")
48	checkPerUserKeyCountLocal(&tc, 2)
49	checkPerUserKeyCount(&tc, 2)
50
51	t.Logf("run the upgrade engine again. Expect an error because the user is already up.")
52	require.False(t, upgrade().DidNewKey, "did not create key")
53
54	t.Logf("check SignedByKID field of the PUKs")
55	loadArg := libkb.NewLoadUserSelfArg(tc.G).WithUID(fu.UID())
56	upak, _, err := tc.G.GetUPAKLoader().LoadV2(loadArg)
57	require.NoError(t, err)
58	require.Len(t, upak.Current.PerUserKeys, 2, "PUK count")
59	var eldest keybase1.KID
60	for _, dkey := range upak.Current.DeviceKeys {
61		if dkey.Base.IsEldest {
62			eldest = dkey.Base.Kid
63		}
64	}
65	require.True(t, eldest.IsValid(), "could not find eldest key")
66	require.Equal(t, eldest, upak.Current.PerUserKeys[0].SignedByKID)
67	require.Equal(t, eldest, upak.Current.PerUserKeys[1].SignedByKID)
68}
69
70func checkPerUserKeyCount(tc *libkb.TestContext, n int) {
71	t := tc.T
72	me, err := libkb.LoadMe(libkb.NewLoadUserForceArg(tc.G))
73	require.NoError(t, err)
74	require.Len(t, me.ExportToUserPlusKeys().PerUserKeys, n, "per-user-key count")
75}
76
77func checkPerUserKeyCountLocal(tc *libkb.TestContext, n int) {
78	t := tc.T
79	pukring, err := tc.G.GetPerUserKeyring(context.Background())
80	require.NoError(t, err)
81	hak := pukring.HasAnyKeys()
82	if n == 0 {
83		require.False(t, hak, "unexpectedly has per-user-key")
84	} else {
85		if !hak {
86			require.FailNow(t, "has no per-user-keys")
87		}
88		require.Equal(t, keybase1.PerUserKeyGeneration(n), pukring.CurrentGeneration(), "wrong latest per-user-key generation")
89	}
90}
91