github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/libkb/skb.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 // 7 // Code for encoding and decoding SKB-formatted keys. Also works for decoding 8 // general Keybase Packet types, but we only have SKB at present. 9 // 10 // SKB = "Secret Key Bundle", which contains an unencrypted public key and 11 // and encrypted secret key. 12 // 13 14 import ( 15 "bytes" 16 "errors" 17 "fmt" 18 "io" 19 "os" 20 "sync" 21 22 "github.com/keybase/client/go/kbcrypto" 23 keybase1 "github.com/keybase/client/go/protocol/keybase1" 24 triplesec "github.com/keybase/go-triplesec" 25 ) 26 27 // DebugDumpKey is used only in debugging. For now it's not in 28 // use but we might need it in the future. 29 func DebugDumpKey(g *GlobalContext, name string, b []byte) { 30 tmp, err := os.CreateTemp(os.TempDir(), "dump-"+name) 31 if err != nil { 32 g.Log.Warning("Failed to dumpKey %s: %s", name, err) 33 return 34 } 35 g.Log.Notice("DUMPKEY %s -> %s", name, tmp.Name()) 36 buf := bytes.NewBuffer(b) 37 _, _ = io.Copy(tmp, buf) 38 tmp.Close() 39 } 40 41 type SKB struct { 42 Priv SKBPriv `codec:"priv"` 43 Pub []byte `codec:"pub"` 44 Type kbcrypto.AlgoType `codec:"type,omitempty"` 45 46 decodedPub GenericKey 47 decryptedSecret GenericKey 48 decryptedRaw []byte // in case we need to reexport it 49 50 uid keybase1.UID // UID that the key is for 51 Contextified 52 53 // TODO(akalin): Remove this in favor of making LKSec 54 // Contextified (see 55 // https://github.com/keybase/client/issues/329 ). 56 newLKSecForTest func(clientHalf LKSecClientHalf) *LKSec 57 58 sync.Mutex // currently only for uid 59 } 60 61 func NewSKB() *SKB { 62 return &SKB{} 63 } 64 65 func NewSKBWithGlobalContext(g *GlobalContext) *SKB { 66 return &SKB{Contextified: NewContextified(g)} 67 } 68 69 type SKBPriv struct { 70 Data []byte `codec:"data"` 71 Encryption int `codec:"encryption"` 72 PassphraseGeneration int `codec:"passphrase_generation,omitempty"` 73 } 74 75 func ToServerSKB(gc *GlobalContext, key GenericKey, tsec Triplesec, gen PassphraseGeneration) (ret *SKB, err error) { 76 if pgp, ok := key.(*PGPKeyBundle); ok { 77 return pgp.ToServerSKB(gc, tsec, gen) 78 } 79 return nil, errors.New("Only PGP keys can be encrypted for server sync") 80 } 81 82 func (key *PGPKeyBundle) ToServerSKB(gc *GlobalContext, tsec Triplesec, gen PassphraseGeneration) (ret *SKB, err error) { 83 84 ret = NewSKBWithGlobalContext(gc) 85 86 var pk, sk bytes.Buffer 87 88 // Need to serialize Private first, because 89 err = key.SerializePrivate(&sk) 90 if err != nil { 91 return 92 } 93 if tsec != nil { 94 ret.Priv.Data, err = tsec.Encrypt(sk.Bytes()) 95 ret.Priv.Encryption = int(ClientTriplesecVersion) 96 if err != nil { 97 return 98 } 99 } else { 100 ret.Priv.Data = sk.Bytes() 101 ret.Priv.Encryption = 0 102 } 103 104 ret.Priv.PassphraseGeneration = int(gen) 105 106 err = key.Entity.Serialize(&pk) 107 if err != nil { 108 return 109 } 110 ret.Pub = pk.Bytes() 111 ret.Type = key.GetAlgoType() 112 113 return 114 } 115 116 func (s *SKB) Dump() { 117 if s == nil { 118 return 119 } 120 s.G().Log.Debug("skb: %+v, uid = %s\n", s, s.uid) 121 } 122 123 func (s *SKB) newLKSec(pps *PassphraseStream) *LKSec { 124 if s.newLKSecForTest != nil { 125 return s.newLKSecForTest(pps.LksClientHalf()) 126 } 127 if s.uid.IsNil() { 128 panic("no uid set in skb") 129 } 130 return NewLKSec(pps, s.uid) 131 } 132 133 func (s *SKB) GetTagAndVersion() (kbcrypto.PacketTag, kbcrypto.PacketVersion) { 134 return kbcrypto.TagP3skb, kbcrypto.KeybasePacketV1 135 } 136 137 func (s *SKB) ReadKey() (g GenericKey, err error) { 138 switch { 139 case IsPGPAlgo(s.Type): 140 var w *Warnings 141 g, w, err = ReadOneKeyFromBytes(s.Pub) 142 w.Warn(s.G()) 143 case s.Type == kbcrypto.KIDNaclEddsa: 144 g, err = ImportNaclSigningKeyPairFromBytes(s.Pub, nil) 145 case s.Type == kbcrypto.KIDNaclDH: 146 g, err = ImportNaclDHKeyPairFromBytes(s.Pub, nil) 147 default: 148 err = UnknownKeyTypeError{s.Type} 149 } 150 return 151 } 152 153 func (s *SKB) GetPubKey() (key GenericKey, err error) { 154 if key = s.decodedPub; key == nil { 155 key, err = s.ReadKey() 156 s.decodedPub = key 157 } 158 return 159 } 160 161 func (s *SKB) VerboseDescription() (ret string, err error) { 162 var key GenericKey 163 key, err = s.GetPubKey() 164 if err == nil && key != nil { 165 ret = key.VerboseDescription() 166 } 167 return 168 } 169 170 func (s *SKB) HumanDescription(owner *User) (string, error) { 171 key, err := s.GetPubKey() 172 if err != nil { 173 return "", err 174 } 175 176 if IsPGPAlgo(s.Type) { 177 return s.pgpHumanDescription(key) 178 } 179 return s.devHumandDescription(owner, key) 180 } 181 182 func (s *SKB) pgpHumanDescription(key GenericKey) (string, error) { 183 pgpKey, ok := key.(*PGPKeyBundle) 184 if !ok { 185 return "", kbcrypto.BadKeyError{Msg: "not pgp key despite skb algo type"} 186 } 187 188 return pgpKey.HumanDescription(), nil 189 } 190 191 func (s *SKB) devHumandDescription(owner *User, key GenericKey) (string, error) { 192 ckf := owner.GetComputedKeyFamily() 193 device, err := ckf.GetDeviceForKey(key) 194 if err != nil { 195 return "", err 196 } 197 if device == nil { 198 return "", NoDeviceError{Reason: fmt.Sprintf("for key ID %s", key.GetKID())} 199 } 200 if device.Description == nil { 201 return "", fmt.Errorf("no device description") 202 } 203 return fmt.Sprintf("Device %q", *device.Description), nil 204 } 205 206 func (s *SKB) RawUnlockedKey() []byte { 207 return s.decryptedRaw 208 } 209 210 func (s *SKB) unlockSecretKeyFromSecretRetriever(m MetaContext, secretRetriever SecretRetriever) (key GenericKey, err error) { 211 defer m.Trace("SKB#unlockSecretKeyFromSecretRetriever", &err)() 212 if key = s.decryptedSecret; key != nil { 213 return 214 } 215 216 var unlocked []byte 217 switch s.Priv.Encryption { 218 case 0: 219 unlocked = s.Priv.Data 220 case LKSecVersion: 221 unlocked, err = s.lksUnlockWithSecretRetriever(m, secretRetriever) 222 default: 223 err = kbcrypto.BadKeyError{Msg: fmt.Sprintf("Can't unlock secret from secret retriever with protection type %d", s.Priv.Encryption)} 224 } 225 226 if err == nil { 227 key, err = s.parseUnlocked(unlocked) 228 } 229 return 230 } 231 232 func (s *SKB) UnlockSecretKey(m MetaContext, passphrase string, tsec Triplesec, pps *PassphraseStream, secretStorer SecretStorer) (key GenericKey, err error) { 233 defer m.Trace("SKB#UnlockSecretKey", &err)() 234 if key = s.decryptedSecret; key != nil { 235 return key, nil 236 } 237 var unlocked []byte 238 239 switch { 240 case s.Priv.Encryption == 0: 241 m.Debug("case: Unlocked") 242 unlocked = s.Priv.Data 243 case s.Priv.Encryption > 0 && s.Priv.Encryption < LKSecVersion: 244 m.Debug("case: Triplesec") 245 tsecIn := tsec 246 if tsec == nil { 247 tsec, err = s.G().NewTriplesec([]byte(passphrase), nil) 248 if err != nil { 249 return nil, err 250 } 251 } 252 unlocked, err = s.tsecUnlock(tsec) 253 if err != nil { 254 return nil, err 255 } 256 if tsecIn == nil { 257 m.Debug("Caching passphrase stream: tsec=%v, pps=%v", (tsec != nil), (pps != nil)) 258 m.ActiveDevice().CachePassphraseStream(NewPassphraseStreamCache(tsec, pps)) 259 } 260 case s.Priv.Encryption == LKSecVersion: 261 m.Debug("case: LKSec") 262 ppsIn := pps 263 if pps == nil { 264 tsec, pps, err = UnverifiedPassphraseStream(m, s.uid, passphrase) 265 if err != nil { 266 return nil, fmt.Errorf("UnlockSecretKey: %s", err) 267 } 268 } 269 unlocked, err = s.lksUnlock(m, pps, secretStorer) 270 if err != nil { 271 return nil, err 272 } 273 if ppsIn == nil { 274 m.Debug("Caching passphrase stream: tsec=%v, pps=%v", (tsec != nil), (pps != nil)) 275 m.ActiveDevice().CachePassphraseStream(NewPassphraseStreamCache(tsec, pps)) 276 } 277 default: 278 err = kbcrypto.BadKeyError{Msg: fmt.Sprintf("Can't unlock secret with protection type %d", s.Priv.Encryption)} 279 return nil, err 280 } 281 key, err = s.parseUnlocked(unlocked) 282 return key, err 283 } 284 285 func (s *SKB) parseUnlocked(unlocked []byte) (key GenericKey, err error) { 286 287 switch { 288 case IsPGPAlgo(s.Type): 289 var w *Warnings 290 key, w, err = ReadOneKeyFromBytes(unlocked) 291 w.Warn(s.G()) 292 case s.Type == kbcrypto.KIDNaclEddsa: 293 key, err = ImportNaclSigningKeyPairFromBytes(s.Pub, unlocked) 294 case s.Type == kbcrypto.KIDNaclDH: 295 key, err = ImportNaclDHKeyPairFromBytes(s.Pub, unlocked) 296 } 297 298 if key == nil { 299 err = kbcrypto.BadKeyError{Msg: "can't parse secret key after unlock"} 300 } 301 if err != nil { 302 return 303 } 304 305 if err = key.CheckSecretKey(); err == nil { 306 s.decryptedRaw = unlocked 307 s.decryptedSecret = key 308 } 309 return 310 } 311 312 func (s *SKB) tsecUnlock(tsec Triplesec) ([]byte, error) { 313 unlocked, err := tsec.Decrypt(s.Priv.Data) 314 if err != nil { 315 if _, ok := err.(triplesec.BadPassphraseError); ok { 316 err = PassphraseError{} 317 } 318 return nil, err 319 } 320 return unlocked, nil 321 } 322 323 func (s *SKB) lksUnlock(m MetaContext, pps *PassphraseStream, secretStorer SecretStorer) (unlocked []byte, err error) { 324 defer m.Trace("SKB#lksUnlock", &err)() 325 m.Debug("| creating new lks") 326 327 lks := s.newLKSec(pps) 328 s.Lock() 329 m.Debug("| setting uid in lks to %s", s.uid) 330 lks.SetUID(s.uid) 331 s.Unlock() 332 var ppGen PassphraseGeneration 333 unlocked, ppGen, _, err = lks.Decrypt(m, s.Priv.Data) 334 if err != nil { 335 return 336 } 337 pps.SetGeneration(ppGen) 338 339 if secretStorer != nil { 340 var secret LKSecFullSecret 341 secret, err = lks.GetSecret(m) 342 if err != nil { 343 unlocked = nil 344 return 345 } 346 // Ignore any errors storing the secret. 347 storeSecretErr := secretStorer.StoreSecret(m, secret) 348 if storeSecretErr != nil { 349 m.Warning("StoreSecret error: %s", storeSecretErr) 350 } 351 } 352 353 return 354 } 355 356 func (s *SKB) lksUnlockWithSecretRetriever(m MetaContext, secretRetriever SecretRetriever) (unlocked []byte, err error) { 357 defer m.Trace("SKB#lksUnlockWithSecretRetriever", &err)() 358 secret, err := secretRetriever.RetrieveSecret(m) 359 if err != nil { 360 return 361 } 362 if s.uid.IsNil() { 363 panic("no uid set in skb") 364 } 365 lks := NewLKSecWithFullSecret(secret, s.uid) 366 unlocked, _, _, err = lks.Decrypt(m, s.Priv.Data) 367 if err != nil { 368 m.Debug("SKB#lksUnlockWithSecretRetriever: failed in lks.Decrypt with uid %q", s.uid) 369 } 370 371 return 372 } 373 374 func (s *SKB) SetUID(uid keybase1.UID) { 375 s.G().Log.Debug("| Setting UID on SKB to %s", uid) 376 s.Lock() 377 s.uid = uid 378 s.Unlock() 379 } 380 381 func (s *SKB) ArmoredEncode() (ret string, err error) { 382 return kbcrypto.EncodePacketToArmoredString(s) 383 } 384 385 func (s *SKB) UnlockWithStoredSecret(m MetaContext, secretRetriever SecretRetriever) (ret GenericKey, err error) { 386 defer m.Trace("SKB#UnlockWithStoredSecret()", &err)() 387 if ret = s.decryptedSecret; ret != nil { 388 return 389 } 390 return s.unlockSecretKeyFromSecretRetriever(m, secretRetriever) 391 } 392 393 var ErrUnlockNotPossible = errors.New("unlock not possible") 394 395 func (s *SKB) UnlockNoPrompt(m MetaContext, secretStore SecretStore) (ret GenericKey, err error) { 396 defer m.Trace("SKB#UnlockNoPrompt", &err)() 397 // already have decrypted secret? 398 if s.decryptedSecret != nil { 399 return s.decryptedSecret, nil 400 } 401 402 // try using the secret store: 403 if secretStore != nil { 404 key, err := s.unlockSecretKeyFromSecretRetriever(m, secretStore) 405 m.Debug("| unlockSecretKeyFromSecretRetriever -> %s", ErrToOk(err)) 406 if err == nil { 407 return key, nil 408 } 409 // fall through if we failed to unlock with retrieved secret... 410 } 411 412 // try using the passphrase stream cache 413 pps, tsec := m.PassphraseStreamAndTriplesec() 414 if tsec != nil || pps != nil { 415 key, err := s.UnlockSecretKey(m, "", tsec, pps, nil) 416 if err == nil { 417 m.Debug("| Unlocked key with cached 3Sec and passphrase stream") 418 return key, nil 419 } 420 if _, ok := err.(PassphraseError); !ok { 421 // not a passphrase error 422 return nil, err 423 } 424 // fall through if it's a passphrase error 425 } else { 426 m.Debug("| No 3Sec or PassphraseStream in UnlockNoPrompt") 427 } 428 429 // failed to unlock without prompting user for passphrase 430 return nil, ErrUnlockNotPossible 431 } 432 433 func (s *SKB) unlockPrompt(m MetaContext, arg SecretKeyPromptArg, secretStore SecretStore, me *User) (ret GenericKey, err error) { 434 defer m.Trace("SKB#unlockPrompt", &err)() 435 436 // check to see if user has recently canceled an unlock prompt: 437 // if lctx != nil, then don't bother as any prompts during login should be shown. 438 if m.LoginContext() == nil && arg.UseCancelCache && m.ActiveDevice().SecretPromptCancelTimer().WasRecentlyCanceled(m) { 439 m.Debug("prompt was recently canceled; skipping") 440 return nil, SkipSecretPromptError{} 441 } 442 443 desc, err := s.HumanDescription(me) 444 if err != nil { 445 return nil, err 446 } 447 448 unlocker := func(pw string, storeSecret bool) (ret GenericKey, err error) { 449 var secretStorer SecretStorer 450 if storeSecret { 451 secretStorer = secretStore 452 } 453 return s.UnlockSecretKey(m, pw, nil, nil, secretStorer) 454 } 455 456 keyUnlocker := NewKeyUnlocker(4, arg.Reason, desc, PassphraseTypeKeybase, (secretStore != nil), arg.SecretUI, unlocker) 457 458 ret, err = keyUnlocker.Run(m) 459 if err != nil { 460 if _, ok := err.(InputCanceledError); ok && arg.UseCancelCache { 461 // cache the cancel response in the account 462 m.ActiveDevice().SecretPromptCancelTimer().SetNow(m) 463 } 464 return nil, err 465 } 466 return ret, nil 467 } 468 469 func (s *SKB) PromptAndUnlock(m MetaContext, arg SecretKeyPromptArg, secretStore SecretStore, me *User) (ret GenericKey, err error) { 470 defer m.Trace(fmt.Sprintf("SKB#PromptAndUnlock(%s)", arg.Reason), &err)() 471 472 // First try to unlock without prompting the user. 473 ret, err = s.UnlockNoPrompt(m, secretStore) 474 if err == nil { 475 return ret, nil 476 } 477 if err != ErrUnlockNotPossible { 478 return nil, err 479 } 480 481 // Prompt necessary: 482 ret, err = s.unlockPrompt(m, arg, secretStore, me) 483 return 484 }