github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/paperkey.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 // PaperKey creates paper backup keys for a user and pushes them to the server. 5 // It checks for existing paper devices and offers to revoke the 6 // keys. 7 // 8 9 package engine 10 11 import ( 12 "fmt" 13 14 "golang.org/x/net/context" 15 16 "github.com/keybase/client/go/libkb" 17 keybase1 "github.com/keybase/client/go/protocol/keybase1" 18 ) 19 20 // PaperKey is an engine. 21 type PaperKey struct { 22 passphrase libkb.PaperKeyPhrase 23 gen *PaperKeyGen 24 libkb.Contextified 25 } 26 27 // NewPaperKey creates a PaperKey engine. 28 func NewPaperKey(g *libkb.GlobalContext) *PaperKey { 29 return &PaperKey{ 30 Contextified: libkb.NewContextified(g), 31 } 32 } 33 34 // Name is the unique engine name. 35 func (e *PaperKey) Name() string { 36 return "PaperKey" 37 } 38 39 // GetPrereqs returns the engine prereqs. 40 func (e *PaperKey) Prereqs() Prereqs { 41 return Prereqs{ 42 Device: true, 43 } 44 } 45 46 // RequiredUIs returns the required UIs. 47 func (e *PaperKey) RequiredUIs() []libkb.UIKind { 48 return []libkb.UIKind{ 49 libkb.LoginUIKind, 50 } 51 } 52 53 // SubConsumers returns the other UI consumers for this engine. 54 func (e *PaperKey) SubConsumers() []libkb.UIConsumer { 55 return []libkb.UIConsumer{ 56 &RevokeEngine{}, 57 &PaperKeyGen{}, 58 } 59 } 60 61 // Run starts the engine. 62 func (e *PaperKey) Run(m libkb.MetaContext) error { 63 m.G().LocalSigchainGuard().Set(m.Ctx(), "PaperKey") 64 defer m.G().LocalSigchainGuard().Clear(m.Ctx(), "PaperKey") 65 66 me, err := libkb.LoadMe(libkb.NewLoadUserArgWithMetaContext(m)) 67 if err != nil { 68 return err 69 } 70 71 // check for existing paper keys 72 cki := me.GetComputedKeyInfos() 73 if cki == nil { 74 return fmt.Errorf("no computed key infos") 75 } 76 77 var needReload bool 78 var devicesToRevoke []*libkb.Device 79 for i, bdev := range cki.PaperDevices() { 80 revoke, err := m.UIs().LoginUI.PromptRevokePaperKeys(context.TODO(), 81 keybase1.PromptRevokePaperKeysArg{ 82 Device: *bdev.ProtExport(), 83 Index: i, 84 }) 85 if err != nil { 86 m.Warning("prompt error: %s", err) 87 return err 88 } 89 if revoke { 90 devicesToRevoke = append(devicesToRevoke, bdev) 91 } 92 } 93 94 // Revoke all keys at once, not one-by-one. This way, a cancelation of the 95 // experience above will stop all operations 96 for _, bdev := range devicesToRevoke { 97 reng := NewRevokeDeviceEngine(m.G(), RevokeDeviceEngineArgs{ID: bdev.ID}) 98 if err := RunEngine2(m, reng); err != nil { 99 // probably not a good idea to continue... 100 return err 101 } 102 needReload = true 103 } 104 105 if needReload { 106 me, err = libkb.LoadMe(libkb.NewLoadUserArgWithMetaContext(m)) 107 if err != nil { 108 return err 109 } 110 } 111 112 ska1 := libkb.SecretKeyArg{ 113 Me: me, 114 KeyType: libkb.DeviceSigningKeyType, 115 } 116 signingKey, err := m.G().Keyrings.GetSecretKeyWithPrompt(m, m.SecretKeyPromptArg(ska1, "You must sign your new paper key")) 117 if err != nil { 118 return err 119 } 120 121 ska2 := libkb.SecretKeyArg{ 122 Me: me, 123 KeyType: libkb.DeviceEncryptionKeyType, 124 } 125 encryptionKeyGeneric, err := m.G().Keyrings.GetSecretKeyWithPrompt(m, m.SecretKeyPromptArg(ska2, "You must encrypt for your new paper key")) 126 if err != nil { 127 return err 128 } 129 encryptionKey, ok := encryptionKeyGeneric.(libkb.NaclDHKeyPair) 130 if !ok { 131 return fmt.Errorf("Unexpected encryption key type") 132 } 133 134 e.passphrase, err = libkb.MakePaperKeyPhrase(libkb.PaperKeyVersion) 135 if err != nil { 136 return err 137 } 138 139 kgarg := &PaperKeyGenArg{ 140 Passphrase: e.passphrase, 141 Me: me, 142 SigningKey: signingKey, 143 EncryptionKey: encryptionKey, 144 PerUserKeyring: nil, 145 } 146 e.gen = NewPaperKeyGen(m.G(), kgarg) 147 if err := RunEngine2(m, e.gen); err != nil { 148 return err 149 } 150 151 return m.UIs().LoginUI.DisplayPaperKeyPhrase(m.Ctx(), keybase1.DisplayPaperKeyPhraseArg{Phrase: e.passphrase.String()}) 152 153 } 154 155 func (e *PaperKey) Passphrase() string { 156 return e.passphrase.String() 157 } 158 159 func (e *PaperKey) SigKey() libkb.GenericKey { 160 return e.gen.SigKey() 161 } 162 163 func (e *PaperKey) EncKey() libkb.GenericKey { 164 return e.gen.EncKey() 165 } 166 167 func (e *PaperKey) DeviceID() keybase1.DeviceID { 168 return e.gen.DeviceID() 169 }