// findAndDecryptPrivatePGPKeys gets the user's private pgp keys if // any exist and decrypts them. func (c *PassphraseChange) findAndDecryptPrivatePGPKeys(ctx *Context) ([]libkb.GenericKey, error) { ska := libkb.SecretKeyArg{ Me: c.me, KeyType: libkb.PGPKeyType, } // get all the pgp key skb blocks from the keyring: var blocks []*libkb.SKB err := c.G().LoginState().Keyring(func(kr *libkb.SKBKeyringFile) { blocks = kr.SearchWithComputedKeyFamily(c.me.GetComputedKeyFamily(), ska) }, "PassphraseChange - findAndDecryptPrivatePGPKey") if err != nil { return nil, err } // and the synced secret keys: syncKeys, err := c.me.AllSyncedSecretKeys(ctx.LoginContext) if err != nil { return nil, err } if syncKeys != nil { blocks = append(blocks, syncKeys...) } secretRetriever := libkb.NewSecretStore(c.G(), c.me.GetNormalizedName()) // avoid duplicates: keys := make(map[keybase1.KID]libkb.GenericKey) for _, block := range blocks { block.SetUID(c.me.GetUID()) var key libkb.GenericKey if c.usingPaper { key, err = block.UnlockWithStoredSecret(secretRetriever) if err != nil { switch err.(type) { case libkb.BadKeyError: // expected error, ok to proceed... continue default: // unexpected error type: return nil, err } } } else { parg := ctx.SecretKeyPromptArg(libkb.SecretKeyArg{}, "passphrase change") key, err = block.PromptAndUnlock(parg, "your keybase passphrase", secretRetriever, nil, c.me) if err != nil { return nil, err } } keys[key.GetKID()] = key } keyList := make([]libkb.GenericKey, 0, len(keys)) for _, key := range keys { keyList = append(keyList, key) } return keyList, nil }
// Push pushes the generated keys to the api server and stores the // local key security server half on the api server as well. func (e *DeviceKeygen) Push(ctx *Context, pargs *DeviceKeygenPushArgs) error { var encSigner libkb.GenericKey eldestKID := pargs.EldestKID ds := []libkb.Delegator{} // append the signing key if pargs.IsEldest { ds = e.appendEldest(ds, ctx, pargs) encSigner = e.naclSignGen.GetKeyPair() eldestKID = encSigner.GetKID() } else if !pargs.SkipSignerPush { ds = e.appendSibkey(ds, ctx, pargs) encSigner = e.naclSignGen.GetKeyPair() } else { encSigner = pargs.Signer } ds = e.appendEncKey(ds, ctx, encSigner, eldestKID, pargs.User) e.pushErr = libkb.DelegatorAggregator(ctx.LoginContext, ds) // push the LKS server half e.pushLKS(ctx) return e.pushErr }
// fetchLKS gets the encrypted LKS client half from the server. // It uses encKey to decrypt it. It also returns the passphrase // generation. func fetchLKS(ctx *Context, g *libkb.GlobalContext, encKey libkb.GenericKey) (libkb.PassphraseGeneration, []byte, error) { arg := libkb.APIArg{ Endpoint: "passphrase/recover", NeedSession: true, Args: libkb.HTTPArgs{ "kid": encKey.GetKID(), }, } if ctx.LoginContext != nil { arg.SessionR = ctx.LoginContext.LocalSession() } res, err := g.API.Get(arg) if err != nil { return 0, nil, err } ctext, err := res.Body.AtKey("ctext").GetString() if err != nil { return 0, nil, err } ppGen, err := res.Body.AtKey("passphrase_generation").GetInt() if err != nil { return 0, nil, err } // Now try to decrypt with the unlocked device key msg, _, err := encKey.DecryptFromString(ctext) if err != nil { return 0, nil, err } return libkb.PassphraseGeneration(ppGen), msg, nil }
// CurrentSession uses the global session to find the session. If // the user isn't logged in, it returns ErrNoSession. func (h *SessionHandler) CurrentSession(_ context.Context, sessionID int) (keybase1.Session, error) { var s keybase1.Session var token string var username libkb.NormalizedUsername var uid keybase1.UID var deviceSubkey libkb.GenericKey var err error aerr := h.G().LoginState().Account(func(a *libkb.Account) { uid, username, token, deviceSubkey, err = a.UserInfo() }, "Service - SessionHandler - UserInfo") if aerr != nil { return s, aerr } if err != nil { if _, ok := err.(libkb.LoginRequiredError); ok { return s, ErrNoSession } return s, err } s.Uid = uid s.Username = username.String() s.Token = token s.DeviceSubkeyKid = deviceSubkey.GetKID() return s, nil }
// fetchLKS gets the encrypted LKS client half from the server. // It uses encKey to decrypt it. It also returns the passphrase // generation. func (c *PassphraseChange) fetchLKS(ctx *Context, encKey libkb.GenericKey) (libkb.PassphraseGeneration, []byte, error) { res, err := c.G().API.Get( libkb.APIArg{ Endpoint: "passphrase/recover", NeedSession: true, Args: libkb.HTTPArgs{ "kid": encKey.GetKID(), }, }) if err != nil { return 0, nil, err } ctext, err := res.Body.AtKey("ctext").GetString() if err != nil { return 0, nil, err } ppGen, err := res.Body.AtKey("passphrase_generation").GetInt() if err != nil { return 0, nil, err } // Now try to decrypt with the unlocked device key msg, _, err := encKey.DecryptFromString(ctext) if err != nil { return 0, nil, err } return libkb.PassphraseGeneration(ppGen), msg, nil }
func (c *PassphraseChange) updatePassphrase(ctx *Context, sigKey libkb.GenericKey, ppGen libkb.PassphraseGeneration, oldClientHalf []byte) error { pgpKeys, err := c.findAndDecryptPrivatePGPKeys(ctx) if err != nil { return err } var acctErr error c.G().LoginState().Account(func(a *libkb.Account) { // Ready the update argument; almost done, but we need some more stuff. payload, err := c.commonArgs(a, oldClientHalf, pgpKeys, ppGen) if err != nil { acctErr = err return } // get the new passphrase hash out of the args pwh, ok := payload["pwh"].(string) if !ok || len(pwh) == 0 { acctErr = fmt.Errorf("no pwh found in common args") return } // Generate a signature with our unlocked sibling key from device. proof, err := c.me.UpdatePassphraseProof(sigKey, pwh, ppGen+1) if err != nil { acctErr = err return } sig, _, _, err := libkb.SignJSON(proof, sigKey) if err != nil { acctErr = err return } payload["sig"] = sig payload["signing_kid"] = sigKey.GetKID() postArg := libkb.APIArg{ Endpoint: "passphrase/sign", NeedSession: true, JSONPayload: payload, SessionR: a.LocalSession(), } _, err = c.G().API.PostJSON(postArg) if err != nil { acctErr = fmt.Errorf("api post to passphrase/sign error: %s", err) return } }, "PassphraseChange.runForcedUpdate") if acctErr != nil { return acctErr } return nil }
func keySolvesProblemTLF(key libkb.GenericKey, tlf keybase1.ProblemTLF) bool { ourKid := key.GetKID() for _, kid := range tlf.Solution_kids { if kid.Equal(ourKid) { return true } } return false }
func logNoMatch(g *libkb.GlobalContext, key libkb.GenericKey, bundles []keybase1.CiphertextBundle) { if key == nil { g.Log.Debug("logNoMatch: key is nil") return } kid := key.GetKID() g.Log.Debug("logNoMatch: desired kid: %s", kid) for i, bundle := range bundles { g.Log.Debug("logNoMatch: kid %d: %s (%v)", i, bundle.Kid, kid.Equal(bundle.Kid)) } }
func kidMatch(key libkb.GenericKey, bundles []keybase1.CiphertextBundle) (int, bool) { if key == nil { return -1, false } kid := key.GetKID() for i, bundle := range bundles { if kid.Equal(bundle.Kid) { return i, true } } return -1, false }
func (e *PGPKeyExportEngine) queryMatch(k libkb.GenericKey) bool { if len(e.arg.Query) == 0 { return true } var match bool switch e.qtype { case either: match = libkb.KeyMatchesQuery(k, e.arg.Query, e.arg.ExactMatch) case fingerprint: match = k.GetFingerprintP().Match(e.arg.Query, e.arg.ExactMatch) case kid: match = k.GetKID().Match(e.arg.Query, e.arg.ExactMatch) } return match }