github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/per_user_key.go (about) 1 package libkb 2 3 import ( 4 "crypto/subtle" 5 "encoding/base64" 6 "errors" 7 "fmt" 8 "sort" 9 "strings" 10 "sync" 11 12 "github.com/keybase/client/go/kbcrypto" 13 keybase1 "github.com/keybase/client/go/protocol/keybase1" 14 "github.com/keybase/go-codec/codec" 15 "golang.org/x/crypto/nacl/secretbox" 16 ) 17 18 const PerUserKeySeedSize = 32 19 20 // A secretbox containg a seed encrypted for its successor generation 21 type PerUserKeyPrev string 22 23 type PerUserKeySeed [PerUserKeySeedSize]byte 24 25 func (s *PerUserKeySeed) DeriveSigningKey() (*NaclSigningKeyPair, error) { 26 derived, err := DeriveFromSecret(*s, DeriveReasonPUKSigning) 27 if err != nil { 28 return nil, err 29 } 30 res, err := MakeNaclSigningKeyPairFromSecret(derived) 31 return &res, err 32 } 33 34 func (s *PerUserKeySeed) DeriveDHKey() (*NaclDHKeyPair, error) { 35 derived, err := DeriveFromSecret(*s, DeriveReasonPUKEncryption) 36 if err != nil { 37 return nil, err 38 } 39 res, err := MakeNaclDHKeyPairFromSecret(derived) 40 return &res, err 41 } 42 43 func (s *PerUserKeySeed) DeriveSymmetricKey(reason DeriveReason) (res NaclSecretBoxKey, err error) { 44 derived, err := DeriveFromSecret(*s, reason) 45 if err != nil { 46 return res, err 47 } 48 return NaclSecretBoxKey(derived), err 49 } 50 51 // derivePrevKey derives the symmetric key used to secretbox the previous generation seed. 52 func (s *PerUserKeySeed) derivePrevKey() (res NaclSecretBoxKey, err error) { 53 return s.DeriveSymmetricKey(DeriveReasonPUKPrev) 54 } 55 56 func (s *PerUserKeySeed) IsBlank() bool { 57 var blank PerUserKeySeed 58 return (subtle.ConstantTimeCompare(s[:], blank[:]) == 1) 59 } 60 61 func NewPerUserKeyBox(contents PerUserKeySeed, receiverKey NaclDHKeyPair, senderKey NaclDHKeyPair, generation keybase1.PerUserKeyGeneration) (keybase1.PerUserKeyBox, error) { 62 if contents.IsBlank() { 63 return keybase1.PerUserKeyBox{}, errors.New("attempt to box blank per-user-key") 64 } 65 66 encInfo, err := receiverKey.Encrypt(contents[:], &senderKey) 67 if err != nil { 68 return keybase1.PerUserKeyBox{}, err 69 } 70 boxStr, err := kbcrypto.EncodePacketToArmoredString(encInfo) 71 if err != nil { 72 return keybase1.PerUserKeyBox{}, err 73 } 74 75 return keybase1.PerUserKeyBox{ 76 Box: boxStr, 77 ReceiverKID: receiverKey.GetKID(), 78 Generation: generation, 79 }, nil 80 } 81 82 // Returns base64 of a msgpack array of 3 items: [version, nonce, box] 83 // Does not do any derivation steps. Caller should pass symmetricKey derived with pukContextPrev. 84 func newPerUserKeyPrev(contents PerUserKeySeed, symmetricKey NaclSecretBoxKey) (PerUserKeyPrev, error) { 85 if contents.IsBlank() { 86 return "", errors.New("attempt to secretbox blank per-user-key") 87 } 88 89 const version = 1 90 91 var nonce [NaclDHNonceSize]byte 92 nonce, err := RandomNaclDHNonce() 93 if err != nil { 94 return "", err 95 } 96 97 // secretbox 98 sealed := secretbox.Seal(nil, contents[:], &nonce, (*[NaclSecretBoxKeySize]byte)(&symmetricKey)) 99 100 parts := []interface{}{version, nonce, sealed} 101 102 // msgpack 103 mh := codec.MsgpackHandle{WriteExt: true} 104 var msgpacked []byte 105 enc := codec.NewEncoderBytes(&msgpacked, &mh) 106 err = enc.Encode(parts) 107 if err != nil { 108 return "", err 109 } 110 111 // b64 112 return PerUserKeyPrev(base64.StdEncoding.EncodeToString(msgpacked)), nil 113 } 114 115 // Opens the output of NewPerUserKeyPrev 116 func openPerUserKeyPrev(sbox PerUserKeyPrev, symmetricKey NaclSecretBoxKey) (PerUserKeySeed, error) { 117 var res PerUserKeySeed 118 119 // decode b64 120 msgpacked, err := base64.StdEncoding.DecodeString(string(sbox)) 121 if err != nil { 122 return res, err 123 } 124 125 // decode msgpack 126 mh := codec.MsgpackHandle{WriteExt: true} 127 dec := codec.NewDecoderBytes(msgpacked, &mh) 128 var parts struct { 129 Version int 130 Nonce []byte 131 Sealed []byte 132 } 133 err = dec.Decode(&parts) 134 if err != nil { 135 return res, err 136 } 137 138 // check parts 139 if parts.Version != 1 { 140 return res, fmt.Errorf("per user key secret box version %v != 1", parts.Version) 141 } 142 143 if len(parts.Nonce) != NaclDHNonceSize { 144 return res, fmt.Errorf("per user key secret box nonce length %v != %v", 145 len(parts.Nonce), NaclDHNonceSize) 146 } 147 var nonce [NaclDHNonceSize]byte 148 copy(nonce[:], parts.Nonce) 149 150 expectedSealedLength := PerUserKeySeedSize + secretbox.Overhead 151 if len(parts.Sealed) != expectedSealedLength { 152 return res, fmt.Errorf("per user key secret box sealed length %v != %v", len(parts.Sealed), expectedSealedLength) 153 } 154 155 // open secretbox 156 var symmetricKey2 [NaclSecretBoxKeySize]byte = symmetricKey 157 contents, ok := secretbox.Open(nil, parts.Sealed, &nonce, &symmetricKey2) 158 if !ok { 159 return res, errors.New("per user key secret box open failed") 160 } 161 if len(contents) != PerUserKeySeedSize { 162 return res, fmt.Errorf("per user key seed length %v != %v", len(contents), PerUserKeySeedSize) 163 } 164 return MakeByte32(contents), nil 165 } 166 167 type perUserKeyFull struct { 168 seed PerUserKeySeed 169 sigKey *NaclSigningKeyPair 170 encKey *NaclDHKeyPair 171 } 172 173 type perUserKeyMap map[keybase1.PerUserKeyGeneration]perUserKeyFull 174 type perUserKeySeqGenMap map[keybase1.Seqno]keybase1.PerUserKeyGeneration 175 176 // PerUserKeyring holds on to all versions of the per user key. 177 // Generation=0 should be nil, but all others should be present. 178 type PerUserKeyring struct { 179 Contextified 180 sync.Mutex 181 uid keybase1.UID 182 generations perUserKeyMap 183 // sigchain seqno when each key was introduced 184 seqgen perUserKeySeqGenMap 185 } 186 187 // NewPerUserKeyring makes a new per-user-key keyring for a given UID. 188 func NewPerUserKeyring(g *GlobalContext, uid keybase1.UID) (*PerUserKeyring, error) { 189 if uid.IsNil() { 190 return nil, fmt.Errorf("NewPerUserKeyring called with nil uid") 191 } 192 return &PerUserKeyring{ 193 Contextified: NewContextified(g), 194 uid: uid, 195 generations: make(perUserKeyMap), 196 seqgen: make(perUserKeySeqGenMap), 197 }, nil 198 } 199 200 func (s *PerUserKeyring) GetUID() keybase1.UID { 201 return s.uid 202 } 203 204 // PrepareBoxForNewDevice encrypts the latest shared key seed for a new device. 205 // The returned box should be pushed to the server. 206 func (s *PerUserKeyring) PrepareBoxForNewDevice(m MetaContext, receiverKey NaclDHKeyPair, 207 senderKey NaclDHKeyPair) (box keybase1.PerUserKeyBox, err error) { 208 s.Lock() 209 defer s.Unlock() 210 211 gen := s.currentGenerationLocked() 212 if gen < 1 { 213 return box, errors.New("PerUserKeyring#PrepareBoxForNewDevice no keys loaded") 214 } 215 full, ok := s.generations[gen] 216 if !ok { 217 return box, errors.New("PerUserKeyring#PrepareBoxForNewDevice missing entry for current generation") 218 } 219 box, err = NewPerUserKeyBox(full.seed, receiverKey, senderKey, gen) 220 return box, err 221 } 222 223 // Encrypt seed for receiverKeys. Use senderKey to encrypt. 224 // Does not use the keyring at all. Attached for organizational purposes. 225 // Used when creating a new seed. 226 func (s *PerUserKeyring) PrepareBoxesForDevices(m MetaContext, contents PerUserKeySeed, 227 generation keybase1.PerUserKeyGeneration, receiverKeys []NaclDHKeyPair, 228 senderKey GenericKey) (boxes []keybase1.PerUserKeyBox, err error) { 229 // Do not lock self because we do not use self. 230 231 if contents.IsBlank() { 232 return nil, errors.New("attempt to box blank per-user-key") 233 } 234 235 senderKeyDH, ok := senderKey.(NaclDHKeyPair) 236 if !ok { 237 return nil, fmt.Errorf("Unexpected encryption key type: %T", senderKey) 238 } 239 240 for _, receiverKey := range receiverKeys { 241 box, err := NewPerUserKeyBox(contents, receiverKey, senderKeyDH, generation) 242 if err != nil { 243 return nil, err 244 } 245 boxes = append(boxes, box) 246 } 247 return boxes, nil 248 } 249 250 // Prepares a prev secretbox containing generation n-1 encrypted for generation n. 251 // Asserts that the current generation is n-1. 252 // The `generation` parameter is n. 253 func (s *PerUserKeyring) PreparePrev(m MetaContext, newSeed PerUserKeySeed, 254 newGeneration keybase1.PerUserKeyGeneration) (PerUserKeyPrev, error) { 255 s.Lock() 256 defer s.Unlock() 257 258 if newSeed.IsBlank() { 259 return "", errors.New("attempt to prev with blank per-user-key") 260 } 261 262 currentGen := s.currentGenerationLocked() 263 if currentGen == 0 { 264 return "", errors.New("attempt to prepare per-user-key prev with no keys") 265 } 266 if currentGen != newGeneration-1 { 267 return "", fmt.Errorf("incompatible prev generations %v != %v-1", currentGen, newGeneration) 268 } 269 270 symmetricKey, err := newSeed.derivePrevKey() 271 if err != nil { 272 return "", err 273 } 274 275 contents := s.generations[currentGen].seed 276 277 return newPerUserKeyPrev(contents, symmetricKey) 278 } 279 280 // AddKey registers a full key locally. 281 func (s *PerUserKeyring) AddKey(m MetaContext, generation keybase1.PerUserKeyGeneration, 282 seqno keybase1.Seqno, seed PerUserKeySeed) error { 283 s.Lock() 284 defer s.Unlock() 285 m.Debug("PerUserKeyring#AddKey(generation: %v, seqno:%v)", generation, seqno) 286 287 if seed.IsBlank() { 288 return errors.New("attempt to add blank per-user-key") 289 } 290 291 currentGen := s.currentGenerationLocked() 292 293 if generation != currentGen+1 { 294 return fmt.Errorf("cannot add key for non-next generation: %v != %v+1", 295 generation, currentGen) 296 } 297 298 _, exists := s.generations[generation] 299 if exists { 300 return fmt.Errorf("AddKey duplicate for generation: %v", generation) 301 } 302 303 expanded, err := expandPerUserKey(seed) 304 if err != nil { 305 return err 306 } 307 308 s.generations[generation] = expanded.lower() 309 s.seqgen[seqno] = generation 310 311 return nil 312 } 313 314 func (s *PerUserKeyring) HasAnyKeys() bool { 315 return s.CurrentGeneration() > 0 316 } 317 318 // CurrentGeneration returns what generation we're on. The version possible 319 // Version is 1. Version 0 implies no keys are available. 320 func (s *PerUserKeyring) CurrentGeneration() keybase1.PerUserKeyGeneration { 321 s.Lock() 322 defer s.Unlock() 323 return s.currentGenerationLocked() 324 } 325 326 func (s *PerUserKeyring) currentGenerationLocked() keybase1.PerUserKeyGeneration { 327 return keybase1.PerUserKeyGeneration(len(s.generations)) 328 } 329 330 func (s *PerUserKeyring) GetLatestSigningKey(m MetaContext) (*NaclSigningKeyPair, error) { 331 s.Lock() 332 defer s.Unlock() 333 gen := s.currentGenerationLocked() 334 if gen < 1 { 335 return nil, errors.New("PerUserKeyring#GetLatestSigningKey no keys loaded") 336 } 337 key, found := s.generations[gen] 338 if !found { 339 return nil, fmt.Errorf("PerUserKeyring#GetLatestSigningKey no key for generation %v", gen) 340 } 341 return key.sigKey, nil 342 } 343 344 func (s *PerUserKeyring) GetSeedByGeneration(m MetaContext, gen keybase1.PerUserKeyGeneration) (res PerUserKeySeed, err error) { 345 s.Lock() 346 defer s.Unlock() 347 if gen < 1 { 348 return res, fmt.Errorf("PerUserKeyring#GetSeedByGeneration bad generation: %v", gen) 349 } 350 if len(s.generations) < 1 { 351 return res, fmt.Errorf("no per-user-keys in keyring") 352 } 353 key, found := s.generations[gen] 354 if !found { 355 return res, fmt.Errorf("no per-user-key for generation: %v", gen) 356 } 357 return key.seed, nil 358 } 359 360 func (s *PerUserKeyring) GetSeedByGenerationOrSync(m MetaContext, gen keybase1.PerUserKeyGeneration) (res PerUserKeySeed, err error) { 361 if seed, err := s.GetSeedByGeneration(m, gen); err == nil { 362 return seed, nil 363 } 364 // Generation was not available, try to sync. 365 if err := s.Sync(m); err != nil { 366 return res, err 367 } 368 return s.GetSeedByGeneration(m, gen) 369 } 370 371 // Get the encryption key of a generation. 372 func (s *PerUserKeyring) GetEncryptionKeyByGeneration(m MetaContext, gen keybase1.PerUserKeyGeneration) (*NaclDHKeyPair, error) { 373 s.Lock() 374 defer s.Unlock() 375 376 return s.getEncryptionKeyByGenerationLocked(m, gen) 377 } 378 379 func (s *PerUserKeyring) GetEncryptionKeyByGenerationOrSync(m MetaContext, gen keybase1.PerUserKeyGeneration) (*NaclDHKeyPair, error) { 380 if key, err := s.GetEncryptionKeyByGeneration(m, gen); err == nil { 381 return key, nil 382 } 383 384 // Generation was not available, try to sync. 385 if err := s.Sync(m); err != nil { 386 return nil, err 387 } 388 return s.GetEncryptionKeyByGeneration(m, gen) 389 } 390 391 func (s *PerUserKeyring) getEncryptionKeyByGenerationLocked(m MetaContext, gen keybase1.PerUserKeyGeneration) (*NaclDHKeyPair, error) { 392 if gen < 1 { 393 return nil, fmt.Errorf("PerUserKeyring#GetEncryptionKey bad generation: %v", gen) 394 } 395 key, found := s.generations[gen] 396 if !found { 397 return nil, fmt.Errorf("no encryption key for generation: %v", gen) 398 } 399 return key.encKey, nil 400 } 401 402 // Get the encryption key at the user sigchain seqno. 403 func (s *PerUserKeyring) GetEncryptionKeyBySeqno(m MetaContext, seqno keybase1.Seqno) (*NaclDHKeyPair, error) { 404 s.Lock() 405 defer s.Unlock() 406 407 gen, ok := s.seqgen[seqno] 408 if !ok { 409 return nil, fmt.Errorf("no encrypted key for seqno %v", seqno) 410 } 411 return s.getEncryptionKeyByGenerationLocked(m, gen) 412 } 413 414 func (s *PerUserKeyring) GetEncryptionKeyBySeqnoOrSync(m MetaContext, seqno keybase1.Seqno) (*NaclDHKeyPair, error) { 415 if key, err := s.GetEncryptionKeyBySeqno(m, seqno); err == nil { 416 return key, nil 417 } 418 // Key at generation from seqno was not available, try to sync. 419 if err := s.Sync(m); err != nil { 420 return nil, err 421 } 422 return s.GetEncryptionKeyBySeqno(m, seqno) 423 } 424 425 // GetEncryptionKeyByKID finds an encryption key that matches kid. 426 func (s *PerUserKeyring) GetEncryptionKeyByKID(m MetaContext, kid keybase1.KID) (*NaclDHKeyPair, error) { 427 s.Lock() 428 defer s.Unlock() 429 430 for _, key := range s.generations { 431 if key.encKey.GetKID().Equal(kid) { 432 return key.encKey, nil 433 } 434 } 435 return nil, NotFoundError{Msg: fmt.Sprintf("no per-user encryption key found for KID %s", kid)} 436 } 437 438 // Sync our PerUserKeyring with the server. It will either add all new 439 // keys since our last update, or not at all if there was an error. 440 // Pass it a standard Go network context. 441 func (s *PerUserKeyring) Sync(m MetaContext) (err error) { 442 return s.syncAsConfiguredDevice(m, nil) 443 } 444 445 // `m.LoginContext` and `upak` are optional 446 func (s *PerUserKeyring) SyncWithExtras(m MetaContext, upak *keybase1.UserPlusAllKeys) (err error) { 447 return s.syncAsConfiguredDevice(m, upak) 448 } 449 450 // `m.LoginContext` and `upak` are optional 451 func (s *PerUserKeyring) syncAsConfiguredDevice(m MetaContext, upak *keybase1.UserPlusAllKeys) (err error) { 452 uv, deviceID, _, _, activeDecryptionKey := m.ActiveDevice().AllFields() 453 if !s.uid.Equal(uv.Uid) { 454 return fmt.Errorf("UID changed on PerUserKeyring") 455 } 456 if deviceID.IsNil() { 457 return fmt.Errorf("missing configured deviceID") 458 } 459 return s.sync(m, upak, deviceID, activeDecryptionKey) 460 } 461 462 // `m.LoginContext` and `upak` are optional 463 func (s *PerUserKeyring) SyncAsProvisioningKey(m MetaContext, upak *keybase1.UserPlusAllKeys, deviceID keybase1.DeviceID, decryptionKey GenericKey) (err error) { 464 if deviceID.IsNil() { 465 return fmt.Errorf("missing deviceID") 466 } 467 // Note this `== nil` check might not work, as it might be a typed nil. 468 if decryptionKey == nil { 469 return fmt.Errorf("missing decryption key") 470 } 471 return s.sync(m, upak, deviceID, decryptionKey) 472 } 473 474 // `m.LoginContext` and `upak` are optional 475 func (s *PerUserKeyring) sync(m MetaContext, upak *keybase1.UserPlusAllKeys, deviceID keybase1.DeviceID, decryptionKey GenericKey) (err error) { 476 defer m.Trace("PerUserKeyring#sync", &err)() 477 478 m.Debug("PerUserKeyring#sync(%v, %v)", m.LoginContext() != nil, upak != nil) 479 480 s.Lock() 481 defer s.Unlock() 482 483 box, prevs, err := s.fetchBoxesLocked(m, deviceID) 484 if err != nil { 485 return err 486 } 487 488 if upak == nil { 489 upak, err = s.getUPAK(m, upak, false) 490 if err != nil { 491 return err 492 } 493 } 494 495 checker := newPerUserKeyChecker(upak) 496 newKeys, err := s.importLocked(m, box, prevs, decryptionKey, checker) 497 if err != nil { 498 return err 499 500 } 501 return s.mergeLocked(newKeys, checker.seqgen) 502 } 503 504 func (s *PerUserKeyring) getUPAK(m MetaContext, upak *keybase1.UserPlusAllKeys, 505 forceReload bool) (*keybase1.UserPlusAllKeys, error) { 506 if upak != nil { 507 return upak, nil 508 } 509 upakArg := NewLoadUserArgWithMetaContext(m).WithUID(s.uid).WithForcePoll( 510 forceReload) 511 upak, _, err := m.G().GetUPAKLoader().Load(upakArg) 512 return upak, err 513 } 514 515 func (s *PerUserKeyring) mergeLocked(m perUserKeyMap, seqgen perUserKeySeqGenMap) (err error) { 516 for k, v := range m { 517 s.generations[k] = v 518 } 519 s.seqgen = seqgen 520 return nil 521 } 522 523 type perUserKeySyncResp struct { 524 Box *keybase1.PerUserKeyBox `json:"box"` 525 Prevs []perUserKeyPrevResp `json:"prevs"` 526 Status AppStatus `json:"status"` 527 } 528 529 func (s *perUserKeySyncResp) GetAppStatus() *AppStatus { 530 return &s.Status 531 } 532 533 type perUserKeyPrevResp struct { 534 Ctext PerUserKeyPrev `json:"ctext"` 535 Generation keybase1.PerUserKeyGeneration `json:"generation"` 536 } 537 538 type byGeneration []perUserKeyPrevResp 539 540 func (m byGeneration) Len() int { return len(m) } 541 func (m byGeneration) Swap(i, j int) { m[i], m[j] = m[j], m[i] } 542 func (m byGeneration) Less(i, j int) bool { return m[i].Generation < m[j].Generation } 543 544 func (s *PerUserKeyring) fetchBoxesLocked(m MetaContext, 545 deviceID keybase1.DeviceID) (box *keybase1.PerUserKeyBox, prevs []perUserKeyPrevResp, err error) { 546 547 defer m.Trace("PerUserKeyring#fetchBoxesLocked", &err)() 548 549 var resp perUserKeySyncResp 550 err = m.G().API.GetDecode(m, APIArg{ 551 Endpoint: "key/fetch_per_user_key_secrets", 552 Args: HTTPArgs{ 553 "generation": I{int(s.currentGenerationLocked())}, 554 "device_id": S{deviceID.String()}, 555 }, 556 SessionType: APISessionTypeREQUIRED, 557 RetryCount: 5, // It's pretty bad to fail this, so retry. 558 }, &resp) 559 if err != nil { 560 return nil, nil, err 561 } 562 m.Debug("| Got back box:%v and prevs:%d from server", resp.Box != nil, len(resp.Prevs)) 563 564 return resp.Box, resp.Prevs, nil 565 } 566 567 // perUserKeyChecker checks the [secret]boxes returned from the server 568 // against the public keys advertised in the user's sigchain. As we import 569 // keys, we check them. We check that the boxes were encrypted with a 570 // valid device subkey (though it can be now revoked). And we check that the 571 // public keys corresponds to what was signed in as a per_user_key. 572 type perUserKeyChecker struct { 573 allowedEncryptingKIDs map[keybase1.KID]bool 574 expectedPUKSigKIDs map[keybase1.PerUserKeyGeneration]keybase1.KID 575 expectedPUKEncKIDs map[keybase1.PerUserKeyGeneration]keybase1.KID 576 latestGeneration keybase1.PerUserKeyGeneration 577 seqgen perUserKeySeqGenMap 578 } 579 580 func newPerUserKeyChecker(upak *keybase1.UserPlusAllKeys) *perUserKeyChecker { 581 ret := perUserKeyChecker{ 582 allowedEncryptingKIDs: make(map[keybase1.KID]bool), 583 expectedPUKSigKIDs: make(map[keybase1.PerUserKeyGeneration]keybase1.KID), 584 expectedPUKEncKIDs: make(map[keybase1.PerUserKeyGeneration]keybase1.KID), 585 latestGeneration: 0, 586 seqgen: make(perUserKeySeqGenMap), 587 } 588 isEncryptionKey := func(k keybase1.PublicKey) bool { 589 return !k.IsSibkey && k.PGPFingerprint == "" 590 } 591 for _, r := range upak.Base.RevokedDeviceKeys { 592 if isEncryptionKey(r.Key) { 593 ret.allowedEncryptingKIDs[r.Key.KID] = true 594 } 595 } 596 for _, k := range upak.Base.DeviceKeys { 597 if isEncryptionKey(k) { 598 ret.allowedEncryptingKIDs[k.KID] = true 599 } 600 } 601 for _, k := range upak.Base.PerUserKeys { 602 ret.expectedPUKSigKIDs[keybase1.PerUserKeyGeneration(k.Gen)] = k.SigKID 603 ret.expectedPUKEncKIDs[keybase1.PerUserKeyGeneration(k.Gen)] = k.EncKID 604 gen := keybase1.PerUserKeyGeneration(k.Gen) 605 ret.seqgen[k.Seqno] = gen 606 if gen > ret.latestGeneration { 607 ret.latestGeneration = gen 608 } 609 } 610 611 return &ret 612 } 613 614 // checkPublic checks that a key matches the KIDs published by the user. 615 func (c *perUserKeyChecker) checkPublic(key importedPerUserKey, generation keybase1.PerUserKeyGeneration) error { 616 // sig key 617 if expectedSigKID, ok := c.expectedPUKSigKIDs[generation]; ok { 618 if !expectedSigKID.SecureEqual(key.sigKey.GetKID()) { 619 return fmt.Errorf("import per-user-key: wrong sigKID expected %v", expectedSigKID.String()) 620 } 621 } else { 622 return fmt.Errorf("import per-user-key: no sigKID for generation: %v", generation) 623 } 624 625 // enc key 626 if expectedEncKID, ok := c.expectedPUKEncKIDs[generation]; ok { 627 if !expectedEncKID.SecureEqual(key.encKey.GetKID()) { 628 return fmt.Errorf("import per-user-key: wrong sigKID expected %v", expectedEncKID.String()) 629 } 630 } else { 631 return fmt.Errorf("import per-user-key: no sigKID for generation: %v", generation) 632 } 633 634 return nil 635 } 636 637 func (s *PerUserKeyring) importLocked(m MetaContext, 638 box *keybase1.PerUserKeyBox, prevs []perUserKeyPrevResp, 639 decryptionKey GenericKey, checker *perUserKeyChecker) (ret perUserKeyMap, err error) { 640 641 defer m.Trace("PerUserKeyring#importLocked", &err)() 642 643 if box == nil && len(prevs) == 0 { 644 // No new stuff, this keyring is up to date. 645 return make(perUserKeyMap), nil 646 } 647 648 if box == nil { 649 return nil, errors.New("per-user-key import nil box") 650 } 651 652 if box.Generation > checker.latestGeneration { 653 // Let's get a new UPAK in case that's just out of date. 654 upak, err := s.getUPAK(m, nil, true) 655 if err != nil { 656 return nil, err 657 } 658 checker = newPerUserKeyChecker(upak) 659 } 660 if box.Generation != checker.latestGeneration { 661 return nil, fmt.Errorf("sync (%v) and checker (%v) disagree on generation", box.Generation, checker.latestGeneration) 662 } 663 664 sort.Sort(sort.Reverse(byGeneration(prevs))) 665 666 var debugPrevGenList []string 667 for _, prev := range prevs { 668 debugPrevGenList = append(debugPrevGenList, fmt.Sprintf("%d", prev.Generation)) 669 } 670 if len(debugPrevGenList) > 0 { 671 m.Debug("PerUserKeyring#importLocked prevs:(%s)", strings.Join(debugPrevGenList, ",")) 672 } 673 674 ret = make(perUserKeyMap) 675 imp1, err := importPerUserKeyBox(box, decryptionKey, checker.latestGeneration, checker) 676 if err != nil { 677 return nil, err 678 } 679 ret[box.Generation] = imp1.lower() 680 681 walkGeneration := box.Generation - 1 682 walkKey := imp1.prevKey 683 for _, prev := range prevs { 684 if walkGeneration <= 0 { 685 return nil, errors.New("per-user-key prev chain too long") 686 } 687 imp, err := importPerUserKeyPrev(walkGeneration, prev, walkKey, walkGeneration, checker) 688 if err != nil { 689 return nil, err 690 } 691 ret[walkGeneration] = imp.lower() 692 693 walkGeneration-- 694 walkKey = imp.prevKey 695 } 696 697 return ret, nil 698 } 699 700 type importedPerUserKey struct { 701 seed PerUserKeySeed 702 sigKey *NaclSigningKeyPair 703 encKey *NaclDHKeyPair 704 // Key used to decrypt the secretbox of the previous generation 705 prevKey NaclSecretBoxKey 706 } 707 708 func (k *importedPerUserKey) lower() perUserKeyFull { 709 return perUserKeyFull{ 710 seed: k.seed, 711 sigKey: k.sigKey, 712 encKey: k.encKey, 713 } 714 } 715 716 // Decrypt, expand, and check a per-user-key from a Box. 717 func importPerUserKeyBox(box *keybase1.PerUserKeyBox, decryptionKey GenericKey, 718 wantedGeneration keybase1.PerUserKeyGeneration, checker *perUserKeyChecker) (*importedPerUserKey, error) { 719 if box == nil { 720 return nil, NewPerUserKeyImportError("per-user-key box nil") 721 } 722 if box.Generation != wantedGeneration { 723 return nil, NewPerUserKeyImportError("bad generation returned: %d", box.Generation) 724 } 725 if !decryptionKey.GetKID().Equal(box.ReceiverKID) { 726 return nil, NewPerUserKeyImportError("wrong encryption kid: %s", box.ReceiverKID.String()) 727 } 728 rawKey, encryptingKID, err := decryptionKey.DecryptFromString(box.Box) 729 if err != nil { 730 return nil, err 731 } 732 if len(checker.allowedEncryptingKIDs) == 0 { 733 return nil, NewPerUserKeyImportError("no allowed encrypting kids") 734 } 735 if !checker.allowedEncryptingKIDs[encryptingKID] { 736 return nil, NewPerUserKeyImportError("unexpected encrypting kid: %s", encryptingKID) 737 } 738 seed, err := MakeByte32Soft(rawKey) 739 if err != nil { 740 return nil, NewPerUserKeyImportError("%s", err) 741 } 742 imp, err := expandPerUserKey(seed) 743 if err != nil { 744 return nil, NewPerUserKeyImportError("%s", err) 745 } 746 err = checker.checkPublic(imp, wantedGeneration) 747 if err != nil { 748 return nil, err 749 } 750 return &imp, nil 751 } 752 753 // Decrypt, expand, and check a per-user-key from a SecretBox. 754 func importPerUserKeyPrev(generation keybase1.PerUserKeyGeneration, prev perUserKeyPrevResp, decryptionKey NaclSecretBoxKey, 755 wantedGeneration keybase1.PerUserKeyGeneration, checker *perUserKeyChecker) (*importedPerUserKey, error) { 756 757 if generation != prev.Generation { 758 return nil, fmt.Errorf("import per-user-key mismatched generation: %v != %v", 759 generation, prev.Generation) 760 } 761 762 seed, err := openPerUserKeyPrev(prev.Ctext, decryptionKey) 763 if err != nil { 764 return nil, err 765 } 766 767 imp, err := expandPerUserKey(seed) 768 if err != nil { 769 return nil, err 770 } 771 772 err = checker.checkPublic(imp, generation) 773 if err != nil { 774 return nil, err 775 } 776 777 return &imp, nil 778 } 779 780 func expandPerUserKey(seed PerUserKeySeed) (res importedPerUserKey, err error) { 781 sigKey, err := seed.DeriveSigningKey() 782 if err != nil { 783 return res, err 784 } 785 encKey, err := seed.DeriveDHKey() 786 if err != nil { 787 return res, err 788 } 789 prevKey, err := seed.derivePrevKey() 790 if err != nil { 791 return res, err 792 } 793 return importedPerUserKey{ 794 seed: seed, 795 sigKey: sigKey, 796 encKey: encKey, 797 prevKey: prevKey, 798 }, nil 799 }