github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/upak.go (about) 1 package libkb 2 3 // UPAK = "User Plus All Keys" 4 5 import ( 6 "fmt" 7 8 "github.com/keybase/client/go/kbcrypto" 9 keybase1 "github.com/keybase/client/go/protocol/keybase1" 10 ) 11 12 // BaseProofSet creates a basic proof set for a user with their 13 // keybase and uid proofs and any pgp fingerprint proofs. 14 func BaseProofSet(u *keybase1.UserPlusKeysV2AllIncarnations) *ProofSet { 15 proofs := []Proof{ 16 {Key: "keybase", Value: u.GetName()}, 17 {Key: "uid", Value: u.GetUID().String()}, 18 } 19 for _, key := range u.Current.PGPKeys { 20 proofs = append(proofs, Proof{Key: PGPAssertionKey, Value: key.Fingerprint.String()}) 21 } 22 return NewProofSet(proofs) 23 } 24 25 // checkKIDPGP checks that the user has the given PGP KID valid *now*. Note that it doesn't 26 // check for revoked PGP keys, and it also does not check key expiration. 27 func checkKIDPGP(u *keybase1.UserPlusKeysV2AllIncarnations, kid keybase1.KID) (found bool) { 28 for _, key := range u.Current.PGPKeys { 29 if key.Base.Kid.Equal(kid) { 30 return true 31 } 32 } 33 return false 34 } 35 36 func checkKIDKeybase(u *keybase1.UserPlusKeysV2AllIncarnations, kid keybase1.KID) (found bool, revokedAt *keybase1.KeybaseTime, deleted bool) { 37 exportRevokedAt := func(key keybase1.PublicKeyV2NaCl) *keybase1.KeybaseTime { 38 if key.Base.Revocation != nil { 39 // This is the inverse of the marshalling we do in rpc_exim.go. 40 return &keybase1.KeybaseTime{ 41 Unix: key.Base.Revocation.Time, 42 Chain: key.Base.Revocation.PrevMerkleRootSigned.Seqno, 43 } 44 } 45 return nil 46 } 47 for _, key := range u.Current.DeviceKeys { 48 if key.Base.Kid.Equal(kid) { 49 found = true 50 revokedAt = exportRevokedAt(key) 51 } 52 } 53 for _, pastIncarnation := range u.PastIncarnations { 54 for _, key := range pastIncarnation.DeviceKeys { 55 if key.Base.Kid.Equal(kid) { 56 found = true 57 deleted = true 58 revokedAt = exportRevokedAt(key) 59 } 60 } 61 } 62 return 63 } 64 65 func CheckKID(u *keybase1.UserPlusKeysV2AllIncarnations, kid keybase1.KID) (found bool, revokedAt *keybase1.KeybaseTime, deleted bool) { 66 if IsPGPAlgo(kbcrypto.AlgoType(kid.GetKeyType())) { 67 found = checkKIDPGP(u, kid) 68 return found, nil, false 69 } 70 return checkKIDKeybase(u, kid) 71 } 72 73 func GetRemoteChainLinkFor(m MetaContext, follower *keybase1.UserPlusKeysV2AllIncarnations, followeeUsername NormalizedUsername, followeeUID keybase1.UID) (ret *TrackChainLink, err error) { 74 defer m.Trace(fmt.Sprintf("UPAK#GetRemoteChainLinkFor(%s,%s,%s)", follower.Current.GetUID(), followeeUsername, followeeUID), &err)() 75 m.VLogf(VLog1, "| Full user: %+v\n", *follower) 76 rtl := follower.GetRemoteTrack(followeeUID) 77 if rtl == nil { 78 m.VLogf(VLog0, "| no remote track found") 79 return nil, nil 80 } 81 if !NewNormalizedUsername(rtl.Username).Eq(followeeUsername) { 82 return nil, UIDMismatchError{Msg: fmt.Sprintf("Usernames didn't match for (%s,%q); got %s", followeeUID, followeeUsername.String(), rtl.Uid)} 83 } 84 if !rtl.Uid.Equal(followeeUID) { 85 return nil, UIDMismatchError{Msg: fmt.Sprintf("UIDs didn't match for (%s,%q); got %s", followeeUID, followeeUsername.String(), rtl.Uid)} 86 } 87 var lid LinkID 88 m.VLogf(VLog0, "| remote track found with linkID=%s", rtl.LinkID) 89 lid, err = ImportLinkID(rtl.LinkID) 90 if err != nil { 91 m.Debug("| Failed to import link ID") 92 return nil, err 93 } 94 var link *ChainLink 95 link, err = ImportLinkFromStorage(m, lid, follower.GetUID()) 96 if err != nil { 97 m.Debug("| failed to import link from storage") 98 return nil, err 99 } 100 if link == nil { 101 m.Debug("| no cached chainlink found") 102 // Such a bug is only possible if the DB cache was reset after 103 // this user was originally loaded in; otherwise, all of this 104 // UPAK's chain links should be available on disk. 105 return nil, InconsistentCacheStateError{} 106 } 107 ret, err = ParseTrackChainLink(GenericChainLink{link}) 108 m.VLogf(VLog0, "| ParseTrackChainLink -> found=%v", (ret != nil)) 109 return ret, err 110 } 111 112 func TrackChainLinkFromUPK2AI(m MetaContext, follower *keybase1.UserPlusKeysV2AllIncarnations, followeeUsername NormalizedUsername, followeeUID keybase1.UID) (*TrackChainLink, error) { 113 tcl, err := GetRemoteChainLinkFor(m, follower, followeeUsername, followeeUID) 114 if err != nil { 115 return nil, err 116 } 117 tcl, err = TrackChainLinkFor(m, follower.Current.Uid, followeeUID, tcl, err) 118 return tcl, err 119 } 120 121 func NormalizedUsernameFromUPK2(u keybase1.UserPlusKeysV2) NormalizedUsername { 122 return NewNormalizedUsername(u.Username) 123 }