github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/engine/pgp_decrypt.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 "github.com/keybase/client/go/protocol/keybase1" 12 ) 13 14 type PGPDecryptArg struct { 15 Source io.Reader 16 Sink io.WriteCloser 17 AssertSigned bool 18 SignedBy string 19 } 20 21 // PGPDecrypt decrypts data read from source into sink for the 22 // logged in user. 23 type PGPDecrypt struct { 24 libkb.Contextified 25 arg *PGPDecryptArg 26 signStatus *libkb.SignatureStatus 27 signer *libkb.User 28 } 29 30 // NewPGPDecrypt creates a PGPDecrypt engine. 31 func NewPGPDecrypt(g *libkb.GlobalContext, arg *PGPDecryptArg) *PGPDecrypt { 32 return &PGPDecrypt{ 33 arg: arg, 34 Contextified: libkb.NewContextified(g), 35 } 36 } 37 38 // Name is the unique engine name. 39 func (e *PGPDecrypt) Name() string { 40 return "PGPDecrypt" 41 } 42 43 // GetPrereqs returns the engine prereqs. 44 func (e *PGPDecrypt) Prereqs() Prereqs { 45 return Prereqs{} 46 } 47 48 // RequiredUIs returns the required UIs. 49 func (e *PGPDecrypt) RequiredUIs() []libkb.UIKind { 50 return []libkb.UIKind{libkb.SecretUIKind, libkb.LogUIKind, libkb.PgpUIKind} 51 } 52 53 // SubConsumers returns the other UI consumers for this engine. 54 func (e *PGPDecrypt) SubConsumers() []libkb.UIConsumer { 55 return []libkb.UIConsumer{ 56 &ScanKeys{}, 57 &ResolveThenIdentify2{}, 58 } 59 } 60 61 // Run starts the engine. 62 func (e *PGPDecrypt) Run(m libkb.MetaContext) (err error) { 63 defer m.Trace("PGPDecrypt#Run", &err)() 64 65 m.Debug("| ScanKeys") 66 sk, err := NewScanKeys(m) 67 if err != nil { 68 return err 69 } 70 m.Debug("| PGPDecrypt") 71 e.signStatus, err = libkb.PGPDecrypt(m.G(), e.arg.Source, e.arg.Sink, sk) 72 if err != nil { 73 return err 74 } 75 76 m.Debug("| Sink Close") 77 if err = e.arg.Sink.Close(); err != nil { 78 return err 79 } 80 81 // get the owner of the signing key 82 e.signer = sk.KeyOwner(e.signStatus.KeyID) 83 84 if len(e.arg.SignedBy) > 0 { 85 e.arg.AssertSigned = true 86 } 87 88 if !e.signStatus.IsSigned { 89 if !e.arg.AssertSigned { 90 return nil 91 } 92 return libkb.BadSigError{E: "no signature in message"} 93 } 94 if !e.signStatus.Verified { 95 return e.signStatus.SignatureError 96 } 97 98 // message is signed and verified 99 100 // generate sha1 warnings for the key bundles 101 if e.signStatus.Entity != nil { 102 if warnings := libkb.NewPGPKeyBundle(e.signStatus.Entity).SecurityWarnings( 103 libkb.HashSecurityWarningSignersIdentityHash, 104 ); warnings != nil { 105 e.signStatus.Warnings = append(e.signStatus.Warnings, warnings...) 106 } 107 } 108 109 if len(e.arg.SignedBy) > 0 { 110 if e.signer == nil { 111 return libkb.BadSigError{ 112 E: fmt.Sprintf("Signer not a keybase user, cannot match signed by assertion %q", e.arg.SignedBy), 113 } 114 } 115 116 // identify the SignedBy assertion 117 arg := keybase1.Identify2Arg{ 118 UserAssertion: e.arg.SignedBy, 119 AlwaysBlock: true, 120 NeedProofSet: true, 121 NoSkipSelf: true, 122 IdentifyBehavior: keybase1.TLFIdentifyBehavior_CLI, 123 } 124 eng := NewResolveThenIdentify2(m.G(), &arg) 125 if err := RunEngine2(m, eng); err != nil { 126 return err 127 } 128 res, err := eng.Result(m) 129 if err != nil { 130 return err 131 } 132 signByUser := res.Upk 133 134 if !signByUser.GetUID().Equal(e.signer.GetUID()) { 135 return libkb.BadSigError{ 136 E: fmt.Sprintf("Signer %q did not match signed by assertion %q", e.signer.GetName(), e.arg.SignedBy), 137 } 138 } 139 } else { 140 if e.signer == nil { 141 // signer isn't a keybase user 142 m.Debug("message signed by key unknown to keybase: %X", e.signStatus.KeyID) 143 if err := OutputSignatureNonKeybase(m, e.signStatus.KeyID, e.signStatus.SignatureTime, e.signStatus.Warnings); err != nil { 144 return err 145 } 146 return libkb.BadSigError{ 147 E: fmt.Sprintf("Message signed by an unknown key: %X", e.signStatus.KeyID), 148 } 149 } 150 151 // identify the signer 152 arg := keybase1.Identify2Arg{ 153 UserAssertion: e.signer.GetName(), 154 AlwaysBlock: true, 155 NeedProofSet: true, 156 NoSkipSelf: true, 157 IdentifyBehavior: keybase1.TLFIdentifyBehavior_CLI, 158 } 159 eng := NewResolveThenIdentify2(m.G(), &arg) 160 if err := RunEngine2(m, eng); err != nil { 161 return err 162 } 163 } 164 165 if e.signStatus.Entity == nil { 166 return libkb.NoKeyError{Msg: fmt.Sprintf("In signature verification: no public key found for PGP ID %x", e.signStatus.KeyID)} 167 } 168 169 if entity := e.signStatus.Entity; len(entity.UnverifiedRevocations) > 0 { 170 return libkb.BadSigError{ 171 E: fmt.Sprintf("Key %x belonging to %q has been revoked by its designated revoker.", entity.PrimaryKey.KeyId, e.signer.GetName()), 172 } 173 } 174 175 bundle := libkb.NewPGPKeyBundle(e.signStatus.Entity) 176 return OutputSignatureSuccess(m, bundle.GetFingerprint(), e.signer, e.signStatus.SignatureTime, e.signStatus.Warnings) 177 } 178 179 func (e *PGPDecrypt) SignatureStatus() *libkb.SignatureStatus { 180 return e.signStatus 181 } 182 183 func (e *PGPDecrypt) Signer() *libkb.User { 184 return e.signer 185 }