github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/special_keys.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libkb 5 6 import ( 7 "sync" 8 9 keybase1 "github.com/keybase/client/go/protocol/keybase1" 10 ) 11 12 // SpecialKeyRing holds blessed keys, like the one Keybase uses to sign 13 // its Merkle Root. 14 type SpecialKeyRing struct { 15 Contextified 16 17 sync.Mutex 18 19 // Cache of keys that are used in verifying the root 20 keys map[keybase1.KID]GenericKey 21 22 // The only ones allowed for this purpose 23 validKIDs map[keybase1.KID]bool 24 } 25 26 // NewSpecialKeyRing allocates a new SpecialKeyRing with the given 27 // vector of KIDs. For NaCl keys, it will actually import those 28 // keys into the Keyring. 29 func NewSpecialKeyRing(v []keybase1.KID, g *GlobalContext) *SpecialKeyRing { 30 ret := &SpecialKeyRing{ 31 keys: make(map[keybase1.KID]GenericKey), 32 validKIDs: make(map[keybase1.KID]bool), 33 Contextified: NewContextified(g), 34 } 35 for _, kid := range v { 36 if key, _ := ImportKeypairFromKID(kid); key != nil { 37 ret.keys[kid] = key 38 } 39 ret.validKIDs[kid] = true 40 } 41 return ret 42 43 } 44 45 // IsValidKID returns if this KID is valid (blessed) according to this Keyring 46 func (sk *SpecialKeyRing) IsValidKID(kid keybase1.KID) bool { 47 val, found := sk.validKIDs[kid] 48 return val && found 49 } 50 51 func LoadPGPKeyFromLocalDB(k keybase1.KID, g *GlobalContext) (*PGPKeyBundle, error) { 52 dbobj, err := g.LocalDb.Get(DbKey{ 53 Typ: DBPGPKey, 54 Key: k.String(), 55 }) 56 if err != nil { 57 return nil, err 58 } 59 if dbobj == nil { 60 return nil, nil 61 } 62 kb, w, err := GetOneKey(dbobj) 63 w.Warn(g) 64 return kb, err 65 } 66 67 // Load takes a blessed KID and returns, if possible, the GenericKey 68 // associated with that KID, for signature verification. If the key isn't 69 // found in memory or on disk (in the case of PGP), then it will attempt 70 // to fetch the key from the keybase server. 71 func (sk *SpecialKeyRing) Load(m MetaContext, kid keybase1.KID) (GenericKey, error) { 72 sk.Lock() 73 defer sk.Unlock() 74 m.Debug("+ SpecialKeyRing.Load(%s)", kid) 75 76 if !sk.IsValidKID(kid) { 77 err := UnknownSpecialKIDError{kid} 78 return nil, err 79 } 80 81 if key, found := sk.keys[kid]; found { 82 m.Debug("- SpecialKeyRing.Load(%s) -> hit inmem cache", kid) 83 return key, nil 84 } 85 86 key, err := LoadPGPKeyFromLocalDB(kid, m.G()) 87 88 if err != nil || key == nil { 89 90 m.Debug("| Load(%s) going to network", kid) 91 var res *APIRes 92 res, err = sk.G().API.Get(m, APIArg{ 93 Endpoint: "key/special", 94 SessionType: APISessionTypeNONE, 95 Args: HTTPArgs{ 96 "kid": S{kid.String()}, 97 }, 98 }) 99 var w *Warnings 100 if err == nil { 101 key, w, err = GetOneKey(res.Body.AtKey("bundle")) 102 } 103 if err == nil { 104 w.Warn(sk.G()) 105 106 if e2 := key.StoreToLocalDb(m.G()); e2 != nil { 107 m.Warning("Failed to store key: %s", e2) 108 } 109 } 110 } else { 111 m.Debug("| Load(%s) hit DB-backed cache", kid) 112 } 113 114 if err == nil && key != nil { 115 sk.keys[kid] = key 116 } 117 118 m.Debug("- SpecialKeyRing.Load(%s)", kid) 119 120 return key, err 121 }