github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/kbfsmd/key_bundle_test.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package kbfsmd
     6  
     7  import (
     8  	"fmt"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/keybase/client/go/kbfs/kbfscodec"
    13  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    14  	"github.com/keybase/client/go/protocol/keybase1"
    15  	"github.com/keybase/go-codec/codec"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  type tlfCryptKeyInfoFuture struct {
    20  	TLFCryptKeyInfo
    21  	kbfscodec.Extra
    22  }
    23  
    24  func (cki tlfCryptKeyInfoFuture) toCurrent() TLFCryptKeyInfo {
    25  	return cki.TLFCryptKeyInfo
    26  }
    27  
    28  func (cki tlfCryptKeyInfoFuture) ToCurrentStruct() kbfscodec.CurrentStruct {
    29  	return cki.toCurrent()
    30  }
    31  
    32  func makeFakeTLFCryptKeyInfoFuture(t *testing.T) tlfCryptKeyInfoFuture {
    33  	id, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(
    34  		keybase1.MakeTestUID(1),
    35  		kbfscrypto.MakeFakeCryptPublicKeyOrBust("fake"),
    36  		kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x3}))
    37  	require.NoError(t, err)
    38  	cki := TLFCryptKeyInfo{
    39  		kbfscrypto.MakeEncryptedTLFCryptKeyClientHalfForTest(
    40  			kbfscrypto.EncryptionSecretbox,
    41  			[]byte("fake encrypted data"),
    42  			[]byte("fake nonce")),
    43  		id, 5,
    44  		codec.UnknownFieldSetHandler{},
    45  	}
    46  	return tlfCryptKeyInfoFuture{
    47  		cki,
    48  		kbfscodec.MakeExtraOrBust("TLFCryptKeyInfo", t),
    49  	}
    50  }
    51  
    52  func TestTLFCryptKeyInfoUnknownFields(t *testing.T) {
    53  	testStructUnknownFields(t, makeFakeTLFCryptKeyInfoFuture(t))
    54  }
    55  
    56  func TestUserServerHalfRemovalInfoAddGeneration(t *testing.T) {
    57  	key1 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key1")
    58  	key2 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key2")
    59  	key3 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key3")
    60  	key4 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key4")
    61  
    62  	half1a := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x1})
    63  	half1b := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x2})
    64  	half1c := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x3})
    65  	half2a := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x4})
    66  	half2b := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x5})
    67  	half2c := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x6})
    68  
    69  	uid := keybase1.MakeTestUID(0x1)
    70  	id1a, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid, key1, half1a)
    71  	require.NoError(t, err)
    72  	id1b, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid, key1, half1b)
    73  	require.NoError(t, err)
    74  	id1c, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid, key1, half1c)
    75  	require.NoError(t, err)
    76  	id2a, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid, key2, half2a)
    77  	require.NoError(t, err)
    78  	id2b, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid, key2, half2b)
    79  	require.NoError(t, err)
    80  	id2c, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid, key2, half2c)
    81  	require.NoError(t, err)
    82  
    83  	// Required because addGeneration may modify its object even
    84  	// if it returns an error.
    85  	makeInfo := func(good bool) UserServerHalfRemovalInfo {
    86  		var key2IDs []kbfscrypto.TLFCryptKeyServerHalfID
    87  		if good {
    88  			key2IDs = []kbfscrypto.TLFCryptKeyServerHalfID{id2a, id2b}
    89  		} else {
    90  			key2IDs = []kbfscrypto.TLFCryptKeyServerHalfID{id2a}
    91  		}
    92  		return UserServerHalfRemovalInfo{
    93  			UserRemoved: true,
    94  			DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
    95  				key1: {id1a, id1b},
    96  				key2: key2IDs,
    97  			},
    98  		}
    99  	}
   100  
   101  	genInfo := UserServerHalfRemovalInfo{
   102  		UserRemoved: false,
   103  	}
   104  
   105  	err = makeInfo(true).addGeneration(uid, genInfo)
   106  	require.Error(t, err)
   107  	require.True(t, strings.HasPrefix(err.Error(), "UserRemoved=true"),
   108  		"err=%v", err)
   109  
   110  	genInfo.UserRemoved = true
   111  	err = makeInfo(true).addGeneration(uid, genInfo)
   112  	require.Error(t, err)
   113  	require.True(t, strings.HasPrefix(err.Error(), "device count=2"),
   114  		"err=%v", err)
   115  
   116  	genInfo.DeviceServerHalfIDs = DeviceServerHalfRemovalInfo{
   117  		key1: {id1c},
   118  		key2: {id2c},
   119  	}
   120  	err = makeInfo(false).addGeneration(uid, genInfo)
   121  	require.Error(t, err)
   122  	require.True(t,
   123  		// Required because of go's random iteration order.
   124  		strings.HasPrefix(err.Error(), "expected 2 keys") ||
   125  			strings.HasPrefix(err.Error(), "expected 1 keys"),
   126  		"err=%v", err)
   127  
   128  	genInfo.DeviceServerHalfIDs = DeviceServerHalfRemovalInfo{
   129  		key1: {},
   130  		key2: {},
   131  	}
   132  	err = makeInfo(true).addGeneration(uid, genInfo)
   133  	require.Error(t, err)
   134  	require.True(t, strings.HasPrefix(err.Error(),
   135  		"expected exactly one key"), "err=%v", err)
   136  
   137  	genInfo.DeviceServerHalfIDs = DeviceServerHalfRemovalInfo{
   138  		key3: {id1c},
   139  		key4: {id2c},
   140  	}
   141  	err = makeInfo(true).addGeneration(uid, genInfo)
   142  	require.Error(t, err)
   143  	require.True(t, strings.HasPrefix(err.Error(),
   144  		"no generation info"), "err=%v", err)
   145  
   146  	genInfo.DeviceServerHalfIDs = DeviceServerHalfRemovalInfo{
   147  		key1: {id1c},
   148  		key2: {id2c},
   149  	}
   150  	info := makeInfo(true)
   151  	err = info.addGeneration(uid, genInfo)
   152  	require.NoError(t, err)
   153  	require.Equal(t, UserServerHalfRemovalInfo{
   154  		UserRemoved: true,
   155  		DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   156  			key1: {id1a, id1b, id1c},
   157  			key2: {id2a, id2b, id2c},
   158  		},
   159  	}, info)
   160  }
   161  
   162  func TestServerHalfRemovalInfoAddGeneration(t *testing.T) {
   163  	key1 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key1")
   164  	key2 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key2")
   165  
   166  	half1a := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x1})
   167  	half1b := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x2})
   168  	half1c := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x3})
   169  	half2a := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x4})
   170  	half2b := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x5})
   171  	half2c := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x6})
   172  
   173  	uid1 := keybase1.MakeTestUID(0x1)
   174  	uid2 := keybase1.MakeTestUID(0x2)
   175  	uid3 := keybase1.MakeTestUID(0x3)
   176  
   177  	id1a, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key1, half1a)
   178  	require.NoError(t, err)
   179  	id1b, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key1, half1b)
   180  	require.NoError(t, err)
   181  	id1c, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key1, half1c)
   182  	require.NoError(t, err)
   183  	id2a, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key2, half2a)
   184  	require.NoError(t, err)
   185  	id2b, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key2, half2b)
   186  	require.NoError(t, err)
   187  	id2c, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key2, half2c)
   188  	require.NoError(t, err)
   189  
   190  	// Required because addGeneration may modify its object even
   191  	// if it returns an error.
   192  	makeInfo := func() ServerHalfRemovalInfo {
   193  		return ServerHalfRemovalInfo{
   194  			uid1: UserServerHalfRemovalInfo{
   195  				UserRemoved: true,
   196  				DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   197  					key1: {id1a, id1b},
   198  					key2: {id2a, id2b},
   199  				},
   200  			},
   201  			uid2: UserServerHalfRemovalInfo{
   202  				UserRemoved: false,
   203  				DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   204  					key1: {id1a, id1c},
   205  					key2: {id2a, id2c},
   206  				},
   207  			},
   208  		}
   209  	}
   210  
   211  	genInfo := ServerHalfRemovalInfo{
   212  		uid1: UserServerHalfRemovalInfo{
   213  			UserRemoved: true,
   214  			DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   215  				key1: {id1c},
   216  				key2: {id2c},
   217  			},
   218  		},
   219  	}
   220  
   221  	err = makeInfo().AddGeneration(genInfo)
   222  	require.Error(t, err)
   223  	require.True(t, strings.HasPrefix(err.Error(), "user count=2"),
   224  		"err=%v", err)
   225  
   226  	genInfo[uid3] = UserServerHalfRemovalInfo{
   227  		UserRemoved: false,
   228  		DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   229  			key1: {id1b},
   230  			key2: {id2b},
   231  		},
   232  	}
   233  
   234  	err = makeInfo().AddGeneration(genInfo)
   235  	require.Error(t, err)
   236  	require.True(t, strings.HasPrefix(err.Error(), "no generation info"),
   237  		"err=%v", err)
   238  
   239  	genInfo[uid2] = UserServerHalfRemovalInfo{
   240  		UserRemoved: true,
   241  		DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   242  			key1: {id1b},
   243  			key2: {id2b},
   244  		},
   245  	}
   246  	delete(genInfo, uid3)
   247  
   248  	err = makeInfo().AddGeneration(genInfo)
   249  	require.Error(t, err)
   250  	require.True(t, strings.HasPrefix(err.Error(), "UserRemoved=false"),
   251  		"err=%v", err)
   252  
   253  	genInfo[uid2] = UserServerHalfRemovalInfo{
   254  		UserRemoved: false,
   255  		DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   256  			key1: {id1b},
   257  			key2: {id2b},
   258  		},
   259  	}
   260  	info := makeInfo()
   261  	err = info.AddGeneration(genInfo)
   262  	require.NoError(t, err)
   263  	require.Equal(t, ServerHalfRemovalInfo{
   264  		uid1: UserServerHalfRemovalInfo{
   265  			UserRemoved: true,
   266  			DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   267  				key1: {id1a, id1b, id1c},
   268  				key2: {id2a, id2b, id2c},
   269  			},
   270  		},
   271  		uid2: UserServerHalfRemovalInfo{
   272  			UserRemoved: false,
   273  			DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   274  				key1: {id1a, id1c, id1b},
   275  				key2: {id2a, id2c, id2b},
   276  			},
   277  		},
   278  	}, info)
   279  }
   280  
   281  func TestServerHalfRemovalInfoMergeUsers(t *testing.T) {
   282  	key1 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key1")
   283  	key2 := kbfscrypto.MakeFakeCryptPublicKeyOrBust("key2")
   284  
   285  	half1a := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x1})
   286  	half1b := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x2})
   287  	half2a := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x3})
   288  	half2b := kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x4})
   289  
   290  	uid1 := keybase1.MakeTestUID(0x1)
   291  	uid2 := keybase1.MakeTestUID(0x2)
   292  	uid3 := keybase1.MakeTestUID(0x3)
   293  	uid4 := keybase1.MakeTestUID(0x4)
   294  
   295  	id1a, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key1, half1a)
   296  	require.NoError(t, err)
   297  	id1b, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key1, half1b)
   298  	require.NoError(t, err)
   299  	id2a, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key2, half2a)
   300  	require.NoError(t, err)
   301  	id2b, err := kbfscrypto.MakeTLFCryptKeyServerHalfID(uid1, key2, half2b)
   302  	require.NoError(t, err)
   303  
   304  	userRemovalInfo := UserServerHalfRemovalInfo{
   305  		UserRemoved: true,
   306  		DeviceServerHalfIDs: DeviceServerHalfRemovalInfo{
   307  			key1: {id1a, id1b},
   308  			key2: {id2a, id2b},
   309  		},
   310  	}
   311  
   312  	info1 := ServerHalfRemovalInfo{
   313  		uid1: userRemovalInfo,
   314  		uid2: userRemovalInfo,
   315  	}
   316  
   317  	info2 := ServerHalfRemovalInfo{
   318  		uid1: userRemovalInfo,
   319  		uid3: userRemovalInfo,
   320  	}
   321  
   322  	_, err = info1.MergeUsers(info2)
   323  	require.Error(t, err)
   324  	require.True(t, strings.HasPrefix(err.Error(),
   325  		fmt.Sprintf("user %s is in both", uid1)),
   326  		"err=%v", err)
   327  
   328  	info2 = ServerHalfRemovalInfo{
   329  		uid3: userRemovalInfo,
   330  		uid4: userRemovalInfo,
   331  	}
   332  
   333  	info3, err := info1.MergeUsers(info2)
   334  	require.NoError(t, err)
   335  	require.Equal(t, ServerHalfRemovalInfo{
   336  		uid1: userRemovalInfo,
   337  		uid2: userRemovalInfo,
   338  		uid3: userRemovalInfo,
   339  		uid4: userRemovalInfo,
   340  	}, info3)
   341  }