github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/pgp_sign.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 "io" 9 10 "github.com/keybase/client/go/libkb" 11 keybase1 "github.com/keybase/client/go/protocol/keybase1" 12 13 "github.com/keybase/go-crypto/openpgp" 14 "github.com/keybase/go-crypto/openpgp/clearsign" 15 ) 16 17 type PGPSignEngine struct { 18 arg *PGPSignArg 19 libkb.Contextified 20 21 warnings libkb.HashSecurityWarnings 22 } 23 24 type PGPSignArg struct { 25 Sink io.WriteCloser 26 Source io.ReadCloser 27 Opts keybase1.PGPSignOptions 28 } 29 30 func (p *PGPSignEngine) Prereqs() Prereqs { 31 return Prereqs{ 32 Device: true, 33 } 34 } 35 36 func (p *PGPSignEngine) Name() string { 37 return "PGPSignEngine" 38 } 39 40 func (p *PGPSignEngine) RequiredUIs() []libkb.UIKind { 41 return []libkb.UIKind{ 42 libkb.SecretUIKind, 43 libkb.PgpUIKind, 44 } 45 } 46 47 func (p *PGPSignEngine) SubConsumers() []libkb.UIConsumer { 48 return nil 49 } 50 51 func NewPGPSignEngine(g *libkb.GlobalContext, arg *PGPSignArg) *PGPSignEngine { 52 return &PGPSignEngine{ 53 arg: arg, 54 Contextified: libkb.NewContextified(g), 55 } 56 } 57 58 func (p *PGPSignEngine) Run(m libkb.MetaContext) (err error) { 59 var key libkb.GenericKey 60 var pgp *libkb.PGPKeyBundle 61 var ok bool 62 var dumpTo io.WriteCloser 63 var written int64 64 65 defer func() { 66 if dumpTo != nil { 67 if e := dumpTo.Close(); e != nil { 68 p.G().Log.Warning("error closing dumpTo: %s", e) 69 } 70 } 71 if e := p.arg.Sink.Close(); e != nil { 72 p.G().Log.Warning("error closing Sink: %s", e) 73 } 74 if e := p.arg.Source.Close(); e != nil { 75 p.G().Log.Warning("error closing Source: %s", e) 76 } 77 }() 78 79 me, err := libkb.LoadMe(libkb.NewLoadUserArg(p.G())) 80 if err != nil { 81 return err 82 } 83 84 ska := libkb.SecretKeyArg{ 85 Me: me, 86 KeyType: libkb.PGPKeyType, 87 KeyQuery: p.arg.Opts.KeyQuery, 88 } 89 key, err = p.G().Keyrings.GetSecretKeyWithPrompt(m, m.SecretKeyPromptArg(ska, "command-line signature")) 90 if err != nil { 91 return 92 } else if pgp, ok = key.(*libkb.PGPKeyBundle); !ok { 93 err = fmt.Errorf("Can only sign with PGP keys") 94 return 95 } 96 97 p.warnings = libkb.HashSecurityWarnings{} 98 if w := pgp.SecurityWarnings( 99 libkb.HashSecurityWarningOurIdentityHash, 100 ); len(w) > 0 { 101 p.warnings = append(p.warnings, w...) 102 } 103 for _, warning := range p.warnings.Strings() { 104 if err := m.UIs().PgpUI.OutputPGPWarning(m.Ctx(), keybase1.OutputPGPWarningArg{ 105 Warning: warning, 106 }); err != nil { 107 return err 108 } 109 } 110 111 bo := p.arg.Opts.BinaryOut 112 bi := p.arg.Opts.BinaryIn 113 pgpe := pgp.Entity 114 mode := p.arg.Opts.Mode 115 116 switch mode { 117 case keybase1.SignMode_ATTACHED: 118 dumpTo, err = libkb.AttachedSignWrapper(p.arg.Sink, *pgp, !bo) 119 case keybase1.SignMode_DETACHED: 120 switch { 121 case bi && bo: 122 err = openpgp.DetachSign(p.arg.Sink, pgpe, p.arg.Source, nil) 123 case bi && !bo: 124 err = openpgp.ArmoredDetachSign(p.arg.Sink, pgpe, p.arg.Source, nil) 125 case !bi && bo: 126 err = openpgp.DetachSignText(p.arg.Sink, pgpe, p.arg.Source, nil) 127 default: 128 err = openpgp.ArmoredDetachSignText(p.arg.Sink, pgpe, p.arg.Source, nil) 129 } 130 case keybase1.SignMode_CLEAR: 131 dumpTo, err = clearsign.Encode(p.arg.Sink, pgp.PrivateKey, nil) 132 default: 133 err = fmt.Errorf("unrecognized sign mode: %d", int(mode)) 134 } 135 136 if err != nil { 137 return 138 } 139 140 if dumpTo != nil { 141 written, err = io.Copy(dumpTo, p.arg.Source) 142 if err == nil && written == 0 { 143 p.G().Log.Debug("Empty source file.") 144 } 145 } 146 return 147 }