github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/pgp_purge.go (about) 1 // Copyright 2016 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 "bytes" 8 "fmt" 9 "os" 10 "path/filepath" 11 12 "github.com/keybase/client/go/libkb" 13 keybase1 "github.com/keybase/client/go/protocol/keybase1" 14 ) 15 16 // PGPPurge is an engine. 17 type PGPPurge struct { 18 libkb.Contextified 19 arg keybase1.PGPPurgeArg 20 me *libkb.User 21 filenames []string 22 } 23 24 // NewPGPPurge creates a PGPPurge engine. 25 func NewPGPPurge(g *libkb.GlobalContext, arg keybase1.PGPPurgeArg) *PGPPurge { 26 return &PGPPurge{ 27 Contextified: libkb.NewContextified(g), 28 arg: arg, 29 } 30 } 31 32 // Name is the unique engine name. 33 func (e *PGPPurge) Name() string { 34 return "PGPPurge" 35 } 36 37 // GetPrereqs returns the engine prereqs. 38 func (e *PGPPurge) Prereqs() Prereqs { 39 return Prereqs{ 40 Device: true, 41 } 42 } 43 44 // RequiredUIs returns the required UIs. 45 func (e *PGPPurge) RequiredUIs() []libkb.UIKind { 46 return []libkb.UIKind{} 47 } 48 49 // SubConsumers returns the other UI consumers for this engine. 50 func (e *PGPPurge) SubConsumers() []libkb.UIConsumer { 51 return []libkb.UIConsumer{ 52 &SaltpackEncrypt{newKeyfinderHook: NewSaltpackUserKeyfinderAsInterface}, 53 } 54 } 55 56 // Run starts the engine. 57 func (e *PGPPurge) Run(m libkb.MetaContext) error { 58 me, err := libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(e.G())) 59 if err != nil { 60 return err 61 } 62 e.me = me 63 64 // get all PGP blocks in keyring 65 ring, err := m.ActiveDevice().Keyring(m) 66 if err != nil { 67 return err 68 } 69 blocks, err := ring.AllPGPBlocks() 70 if err != nil { 71 return err 72 } 73 74 // export each one to a file 75 if err := e.exportBlocks(m, blocks); err != nil { 76 return err 77 } 78 79 if e.arg.DoPurge { 80 // if purge flag set, remove all PGP blocks from keyring and save it 81 err = ring.RemoveAllPGPBlocks() 82 if err != nil { 83 return err 84 } 85 err = ring.Save() 86 if err != nil { 87 return err 88 } 89 } 90 91 return nil 92 } 93 94 // KeyFiles returns the filenames of the exported keys. 95 func (e *PGPPurge) KeyFiles() []string { 96 return e.filenames 97 } 98 99 func (e *PGPPurge) exportBlocks(m libkb.MetaContext, blocks []*libkb.SKB) error { 100 sstore := libkb.NewSecretStore(m, e.me.GetNormalizedName()) 101 promptArg := libkb.SecretKeyPromptArg{ 102 SecretUI: m.UIs().SecretUI, 103 Reason: "export private PGP key", 104 } 105 106 for i, block := range blocks { 107 block.SetUID(e.me.GetUID()) 108 key, err := block.PromptAndUnlock(m, promptArg, sstore, e.me) 109 if err != nil { 110 return err 111 } 112 113 pgpKey, ok := key.(*libkb.PGPKeyBundle) 114 if !ok { 115 return fmt.Errorf("unlocked key incorrect type") 116 } 117 118 name := fmt.Sprintf("kb-%04d-%s.saltpack", i, pgpKey.GetFingerprint()) 119 path := filepath.Join(e.G().Env.GetConfigDir(), name) 120 if err := e.encryptToFile(m, pgpKey, path); err != nil { 121 return err 122 } 123 124 e.filenames = append(e.filenames, path) 125 } 126 127 return nil 128 } 129 130 func (e *PGPPurge) encryptToFile(m libkb.MetaContext, bundle *libkb.PGPKeyBundle, filename string) error { 131 out, err := os.Create(filename) 132 if err != nil { 133 return err 134 } 135 defer out.Close() 136 137 var buf bytes.Buffer 138 if err := bundle.EncodeToStream(libkb.NopWriteCloser{W: &buf}, true); err != nil { 139 return err 140 } 141 142 // encrypt 143 arg := &SaltpackEncryptArg{ 144 Source: &buf, 145 Sink: out, 146 Opts: keybase1.SaltpackEncryptOptions{ 147 Recipients: []string{m.CurrentUsername().String()}, 148 AuthenticityType: keybase1.AuthenticityType_SIGNED, 149 UsePaperKeys: true, 150 UseDeviceKeys: true, 151 UseEntityKeys: true, 152 }, 153 } 154 eng := NewSaltpackEncrypt(arg, NewSaltpackUserKeyfinderAsInterface) 155 return RunEngine2(m, eng) 156 }