github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/common.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 engine 5 6 import ( 7 "fmt" 8 9 "github.com/keybase/client/go/libkb" 10 ) 11 12 // findPaperKeys checks if the user has paper backup keys. If he/she 13 // does, it prompts for a paperkey phrase. This is used to 14 // regenerate paper keys, which are then matched against the 15 // paper keys found in the keyfamily. 16 func findPaperKeys(m libkb.MetaContext, me *libkb.User) (*libkb.DeviceWithKeys, error) { 17 cki := me.GetComputedKeyInfos() 18 if cki == nil { 19 return nil, fmt.Errorf("no computed key infos") 20 } 21 bdevs := cki.PaperDevices() 22 if len(bdevs) == 0 { 23 return nil, libkb.NoPaperKeysError{} 24 } 25 26 passphrase, err := libkb.GetPaperKeyPassphrase(m, m.UIs().SecretUI, me.GetName(), nil, nil) 27 if err != nil { 28 return nil, err 29 } 30 31 return matchPaperKey(m, me, passphrase) 32 } 33 34 // matchPaperKey checks to make sure paper is a valid paper phrase and that it exists 35 // in the user's keyfamily. 36 func matchPaperKey(m libkb.MetaContext, me *libkb.User, paper string) (*libkb.DeviceWithKeys, error) { 37 cki := me.GetComputedKeyInfos() 38 if cki == nil { 39 return nil, fmt.Errorf("no computed key infos") 40 } 41 bdevs := cki.PaperDevices() 42 if len(bdevs) == 0 { 43 return nil, libkb.NoPaperKeysError{} 44 } 45 46 pc := new(libkb.PaperChecker) 47 if err := pc.Check(m, paper); err != nil { 48 return nil, err 49 } 50 51 // phrase has the correct version and contains valid words 52 53 paperPhrase := libkb.NewPaperKeyPhrase(paper) 54 55 bkarg := &PaperKeyGenArg{ 56 Passphrase: paperPhrase, 57 SkipPush: true, 58 Me: me, 59 } 60 bkeng := NewPaperKeyGen(m.G(), bkarg) 61 if err := RunEngine2(m, bkeng); err != nil { 62 return nil, err 63 } 64 65 sigKey := bkeng.SigKey() 66 encKey := bkeng.EncKey() 67 var device *libkb.Device 68 69 m.Debug("generated paper key signing kid: %s", sigKey.GetKID()) 70 m.Debug("generated paper key encryption kid: %s", encKey.GetKID()) 71 72 ckf := me.GetComputedKeyFamily() 73 for _, bdev := range bdevs { 74 sk, err := ckf.GetSibkeyForDevice(bdev.ID) 75 if err != nil { 76 m.Debug("ckf.GetSibkeyForDevice(%s) error: %s", bdev.ID, err) 77 continue 78 } 79 m.Debug("paper key device %s signing kid: %s", bdev.ID, sk.GetKID()) 80 ek, err := ckf.GetEncryptionSubkeyForDevice(bdev.ID) 81 if err != nil { 82 m.Debug("ckf.GetEncryptionSubkeyForDevice(%s) error: %s", bdev.ID, err) 83 continue 84 } 85 m.Debug("paper key device %s encryption kid: %s", bdev.ID, ek.GetKID()) 86 87 if sk.GetKID().Equal(sigKey.GetKID()) && ek.GetKID().Equal(encKey.GetKID()) { 88 m.Debug("paper key device %s matches generated paper key", bdev.ID) 89 device = bdev 90 break 91 } 92 93 m.Debug("paper key device %s does not match generated paper key", bdev.ID) 94 } 95 96 if device == nil { 97 m.Debug("no matching paper keys found") 98 return nil, libkb.PassphraseError{Msg: "no matching paper backup keys found"} 99 } 100 101 var deviceName string 102 if device.Description != nil { 103 deviceName = *device.Description 104 } 105 return libkb.NewDeviceWithKeys(sigKey, encKey, device.ID, deviceName, libkb.KeychainModeNone), nil 106 } 107 108 // fetchLKS gets the encrypted LKS client half from the server. 109 // It uses encKey to decrypt it. It also returns the passphrase 110 // generation. 111 func fetchLKS(m libkb.MetaContext, encKey libkb.GenericKey) (libkb.PassphraseGeneration, libkb.LKSecClientHalf, error) { 112 arg := libkb.APIArg{ 113 Endpoint: "passphrase/recover", 114 SessionType: libkb.APISessionTypeREQUIRED, 115 Args: libkb.HTTPArgs{ 116 "kid": encKey.GetKID(), 117 }, 118 } 119 res, err := m.G().API.Get(m, arg) 120 var dummy libkb.LKSecClientHalf 121 if err != nil { 122 return 0, dummy, err 123 } 124 ctext, err := res.Body.AtKey("ctext").GetString() 125 if err != nil { 126 return 0, dummy, err 127 } 128 ppGen, err := res.Body.AtKey("passphrase_generation").GetInt() 129 if err != nil { 130 return 0, dummy, err 131 } 132 133 // Now try to decrypt with the unlocked device key 134 msg, _, err := encKey.DecryptFromString(ctext) 135 if err != nil { 136 return 0, dummy, err 137 } 138 clientHalf, err := libkb.NewLKSecClientHalfFromBytes(msg) 139 if err != nil { 140 return 0, dummy, err 141 } 142 143 return libkb.PassphraseGeneration(ppGen), clientHalf, nil 144 }