github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/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 }