Hi Albert. OK. I see that it works for a command-line program (I didn't know about qcatool, to be honest). Perhaps I didn't make it clear, but my project is a GUI program, using Qt5. Currently, QCA invokes the gpg executable (although I gather there are plans to switch to GPGME), and there are, as far as I know, only three ways to feed gpg with a passphrase when it needs one:
- Have gpg request it directly on the console, as you describe, - Directly, on the command line (not a good idea), and - Via gpg-agent. gpg, when invoked manually, opens up a pinentry dialog, which collects the passphrase and feeds it to gpg-agent. QCA doesn't seem to contain the necessary assuan code to do that. Furthermore, it can't request for it on the console because it forces "--pinentry-mode loopback", which suppresses that. Besides, you don't want to use the console for anything when you're running a GUI program. Since QCA invokes the gpg executable anyway, it makes more sense to just let gpg bring up a pinentry dialog. I've attached the patch that fixes the library to do just that. I don't think it adds much more than 10-12 lines to the code. Thanks, .....Ron -- Ron Murray <r...@rjmx.net> PGP Fingerprint: 4D99 70E3 2317 334B 141E 7B63 12F7 E865 B5E2 E761 On Sat, 2022-09-10 at 11:31 +0200, Albert Astals Cid wrote: > El dissabte, 10 de setembre de 2022, a les 5:00:26 (CEST), Ron Murray > va > escriure: > > I'm working on a project using Qt5, GPG and QCA2, the latter > > because > > it can encrypt and decrypt PGP messages. This, of course, involves > > using the qca-gnupg plugin. > > > > Encryption went fine (there's no need to sign anything (at the > > moment, anyway)). Decryption, however, presented a problem: How to > > get > > the password into gpg? I tried following the one example that I > > could > > find (eventhandlerdemo.cpp), but I could never get the > > PasswordAsker > > to, you know, actually ask for a password. > > Works fine here [1], i do > > ./bin/qcatool-qt5 message encrypt pgp P:df11 > > being df11 the short descriptor [2] of my key that has a passphrase, > enter > some > text on the command line and press Ctrl+D and then run > > ./bin/qcatool-qt5 message decrypt pgp > paste the text on the command line that the encrypt process entered, > press > Ctrl+D > > and feed it that and it ends up in the PassphrasePrompt class code > asking my > passphrase on the command line. > > Cheers, > Albert > > [1] Well, it needs a fix in the qcatool code, but that's > "irrelevant", the > library code is fine. > https://invent.kde.org/libraries/qca/-/merge_requests/89/diffs > > [2] you can use > qcatool-qt5 keystore list-stores > and > qcatool-qt5 keystore list ID_OF_THE_GPG_KEYRING > to try to find your short id if needed > > > I did discover, however, > > that if I first used gpg to decrypt something (and supplying my > > password to the agent in the process), that my program would > > successfully decrypt things until the agent timed out (i.e. ten > > minutes > > or so). > > > > I began to think that the problem lay in the qca2 library. I > > went > > through the source code and did a bit of tracing, and I found that > > QCA > > always supplies "--pinentry-mode loopback" on the gpg command line. > > This will never invoke the pinentry dialog, because that mode > > forces > > gpg to ask for a password on the command line, which, apart from > > being > > useless in a GUI application, won't work anyway because QCA also > > supplies "--no-tty" on the command line, and that suppresses > > console > > output. > > > > I managed to modify the qca-gnupg plugin code to replace "-- > > pinentry-mode loopback" with "--pinentry-mode default" when it's > > decrypting or signing a message, built the libraries, installed it, > > and > > now I get a proper pinentry dialog when I want to decrypt a > > message. > > > > So, the questions that I have are these: > > > > 1. I don't think that QCA, on its own, has any way to supply a > > password > > to gpg or gpg-agent (apart, I suppose, by supplying it on the > > command > > line, and nobody wants that), and anyway it's not implemented. But > > have > > I missed something? Has anyone got QCA to decrypt files with GPG > > lately? > > > > 2. Would this patch be useful for others? Note that it only affects > > the > > qca-gnupg plugin: the rest of QCA is untouched. > > > > I'm using the current QCA version on Debian testing (2.3.4- > > 1+b1). > > > >
--- qca2-2.3.4.orig/plugins/qca-gnupg/gpgaction.cpp +++ qca2-2.3.4/plugins/qca-gnupg/gpgaction.cpp @@ -329,6 +329,7 @@ void GpgAction::start() extra = true; collectOutput = false; allowInput = true; + proc.needPass = true; if (input.opt_ascii) writeText = true; break; @@ -341,6 +342,7 @@ void GpgAction::start() extra = true; collectOutput = false; allowInput = true; + proc.needPass = true; if (input.opt_ascii) readText = true; signing = true; @@ -361,6 +363,7 @@ void GpgAction::start() extra = true; collectOutput = false; allowInput = true; + proc.needPass = true; if (input.opt_ascii) readText = true; signing = true; --- qca2-2.3.4.orig/plugins/qca-gnupg/gpgproc/gpgproc.cpp +++ qca2-2.3.4/plugins/qca-gnupg/gpgproc/gpgproc.cpp @@ -27,6 +27,8 @@ using namespace QCA; namespace gpgQCAPlugin { +bool GPGProc::needPass; + void releaseAndDeleteLater(QObject *owner, QObject *obj) { obj->disconnect(owner); @@ -166,7 +168,12 @@ void GPGProc::Private::setupArguments() QStringList fullargs; fullargs += QStringLiteral("--no-tty"); fullargs += QStringLiteral("--pinentry-mode"); - fullargs += QStringLiteral("loopback"); + + // Change pinentry-mode if we need to get a passphrase from the user + if (needPass) + fullargs += QStringLiteral("default"); + else + fullargs += QStringLiteral("loopback"); if (mode == ExtendedMode) { fullargs += QStringLiteral("--enable-special-filenames"); @@ -459,6 +466,7 @@ GPGProc::GPGProc(QObject *parent) : QObject(parent) { d = new Private(this); + needPass = false; } GPGProc::~GPGProc() --- qca2-2.3.4.orig/plugins/qca-gnupg/gpgproc/gpgproc.h +++ qca2-2.3.4/plugins/qca-gnupg/gpgproc/gpgproc.h @@ -64,6 +64,7 @@ public: void closeStdin(); void closeAux(); void closeCommand(); + static bool needPass; Q_SIGNALS: void error(gpgQCAPlugin::GPGProc::Error error);
signature.asc
Description: This is a digitally signed message part