github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/upak2_test.go (about)

     1  package engine
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/keybase/client/go/libkb"
     8  	"github.com/keybase/client/go/protocol/keybase1"
     9  	"github.com/stretchr/testify/require"
    10  	"golang.org/x/net/context"
    11  )
    12  
    13  func TestExportAllIncarnationsAfterReset(t *testing.T) {
    14  	// One context for user that will be doing LoadUser, and another
    15  	// for user that will sign up and reset itself.
    16  	tc := SetupEngineTest(t, "clu")
    17  	defer tc.Cleanup()
    18  
    19  	resetUserTC := SetupEngineTest(t, "clu2")
    20  	defer resetUserTC.Cleanup()
    21  
    22  	// The first version of this user has just a PGP key. We'll assert that
    23  	// that's reflected in the export at the end.
    24  	t.Logf("create new user")
    25  	fu := createFakeUserWithPGPOnly(t, resetUserTC)
    26  
    27  	// Reset this user's account.
    28  	ResetAccount(resetUserTC, fu)
    29  
    30  	// Now provision it with regular device keys, and no PGP key.
    31  	fu.LoginOrBust(resetUserTC)
    32  	if err := AssertProvisioned(resetUserTC); err != nil {
    33  		t.Fatal(err)
    34  	}
    35  
    36  	arg := libkb.NewLoadUserByNameArg(tc.G, fu.Username)
    37  	u, err := libkb.LoadUser(arg)
    38  	require.NoError(t, err)
    39  
    40  	exported, err := u.ExportToUPKV2AllIncarnations()
    41  	require.NoError(t, err)
    42  
    43  	if len(exported.PastIncarnations) != 1 {
    44  		t.Fatalf("Expected exactly 1 past incarnation, found %d", len(exported.PastIncarnations))
    45  	}
    46  
    47  	current := exported.Current
    48  	past := exported.PastIncarnations[0]
    49  
    50  	// Check that the current user has device keys and no PGP key.
    51  	if len(current.PGPKeys) != 0 {
    52  		t.Fatalf("Expected exactly 0 PGP keys in the current incarnation, found %d", len(current.PGPKeys))
    53  	}
    54  	if len(current.DeviceKeys) != 2 {
    55  		t.Fatalf("Expected exactly 2 device keys in the current incarnation, found %d", len(current.DeviceKeys))
    56  	}
    57  
    58  	// Check that the past version of the user has a PGP key but no device keys.
    59  	if len(past.PGPKeys) != 1 {
    60  		t.Fatalf("Expected exactly 1 PGP key in the past incarnation, found %d", len(past.PGPKeys))
    61  	}
    62  	if len(past.DeviceKeys) != 0 {
    63  		t.Fatalf("Expected exactly 0 device keys in the past incarnation, found %d", len(past.DeviceKeys))
    64  	}
    65  
    66  	// Make sure the timestamps on keys are exported properly.
    67  	for _, key := range current.DeviceKeys {
    68  		userKeyInfo := u.GetComputedKeyInfos().Infos[key.Base.Kid]
    69  		t1 := keybase1.FromTime(key.Base.CTime)
    70  		t2 := time.Unix(userKeyInfo.CTime, 0)
    71  		if !t1.Equal(t2) {
    72  			t.Fatalf("exported key ctime is not equal: %s != %s", t1, t2)
    73  		}
    74  	}
    75  
    76  	// Make sure all the chain links made it into the link IDs list.
    77  	if len(exported.SeqnoLinkIDs) != int(u.GetSigChainLastKnownSeqno()) {
    78  		t.Fatalf("expected SeqnoLinkIDs to be len %d but found %d", u.GetSigChainLastKnownSeqno(), len(exported.SeqnoLinkIDs))
    79  	}
    80  	// Make sure all seqnos are present.
    81  	for seqno := 1; seqno <= len(exported.SeqnoLinkIDs); seqno++ {
    82  		linkID, ok := exported.SeqnoLinkIDs[keybase1.Seqno(seqno)]
    83  		if !ok {
    84  			t.Fatalf("seqno %d missing from link IDs map", seqno)
    85  		}
    86  		if len(linkID) == 0 {
    87  			t.Fatalf("found empty LinkID at seqno %d, that's pretty weird", seqno)
    88  		}
    89  	}
    90  
    91  	// Make sure the eldest key has delegation info populated correctly.
    92  	foundEldest := false
    93  	for _, key := range exported.Current.DeviceKeys {
    94  		if !key.Base.IsEldest {
    95  			continue
    96  		}
    97  		if foundEldest {
    98  			t.Fatal("found a second eldest key?!")
    99  		}
   100  		foundEldest = true
   101  		if key.Base.Provisioning.Time.IsZero() {
   102  			t.Fatal("eldest key provisioning info appears uninitialized")
   103  		}
   104  	}
   105  
   106  	require.Nil(t, current.Reset)
   107  	reset := past.Reset
   108  	require.NotNil(t, reset)
   109  	require.Equal(t, reset.ResetSeqno, keybase1.Seqno(1))
   110  	require.True(t, reset.Ctime > keybase1.UnixTime(1419826703))
   111  	require.True(t, reset.MerkleRoot.Seqno > keybase1.Seqno(0))
   112  	require.Equal(t, reset.Type, keybase1.ResetType_RESET)
   113  	require.Equal(t, reset.EldestSeqno, keybase1.Seqno(1))
   114  
   115  	// Test libkb.FindNextMerkleRootAfterReset --- in this case, the next merkle root
   116  	// in the sequence should be the right one.
   117  	m := NewMetaContextForTest(tc)
   118  	fnmrArg := keybase1.FindNextMerkleRootAfterResetArg{
   119  		Uid:        u.GetUID(),
   120  		ResetSeqno: keybase1.Seqno(1),
   121  		Prev:       reset.MerkleRoot,
   122  	}
   123  	res, err := libkb.FindNextMerkleRootAfterReset(m, fnmrArg)
   124  	require.NoError(t, err)
   125  	require.NotNil(t, res.Res)
   126  	require.True(t, res.Res.Seqno > reset.MerkleRoot.Seqno)
   127  
   128  	// While we're here, also check that UPK v1 has the right reset summaries.
   129  	upk1, err := libkb.LoadUserPlusKeys(context.TODO(), tc.G, fu.UID(), keybase1.KID(""))
   130  	require.NoError(t, err)
   131  	require.Equal(t, len(upk1.Resets), 1)
   132  	require.Equal(t, upk1.Resets[0].EldestSeqno, keybase1.Seqno(1))
   133  	require.Equal(t, upk1.Resets[0].Type, keybase1.ResetType_RESET)
   134  
   135  }