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  }