QtPass 2.0.0
Developer documentation
Loading...
Searching...
No Matches
GpgIdSigner Class Reference

The detached signature on a store's .gpg-id: whether the configured signing key is usable, signing the file, and checking that an existing .gpg-id.sig was made by one of the configured keys. More...

#include <gpgidsigner.h>

Public Types

using Exec
 Blocking process runner: Executor::executeBlocking()'s shape.

Public Member Functions

 GpgIdSigner (QString gpgExecutable, QStringList signingKeys, Exec exec=Exec())
 Create a signer.
auto enabled () const -> bool
 Whether any signing key is configured at all.
auto keys () const -> const QStringList &
 The keys this signer was given.
auto haveSecretKey () const -> bool
 Whether gpg has the secret key that sign() will use, i.e. the first configured key.
auto sign (const QString &gpgIdFile, const QByteArray &contents, QString *error=nullptr) const -> bool
 Write <file>.sig, a detached signature by the first key over contents, the bytes the caller just wrote as gpgIdFile.
auto verify (const QByteArray &contents, const QString &signatureFile) const -> bool
 Check a detached signature against the given bytes: gpg must report a VALIDSIG whose key or primary-key fingerprint is one of the configured keys.
auto verifyFile (const QString &gpgIdFile, QByteArray *contents) const -> bool
 Read gpgIdFile and verify it against <file>.sig.

Static Public Member Functions

static auto keysFromSetting (const QString &passSigningKey) -> QStringList
 Split the settings value into keys, upper-cased the way gpg prints fingerprints.
static auto validSigFingerprints (const QString &statusOutput) -> QStringList
 Pick the fingerprints out of gpg's --status-fd VALIDSIG line.

Static Public Attributes

static constexpr qint64 kMaxSignatureBytes = 64 * 1024
 Most bytes of a .gpg-id.sig verify() hands to gpg.

Private Member Functions

auto run (const QStringList &args, QString *out=nullptr, QString *err=nullptr, const QString &input=QString()) const -> int
 Run gpg with args through m_exec.

Private Attributes

QString m_gpg
 The gpg executable, as configured.
QStringList m_keys
 The configured signing keys. The first one signs; a signature by any of them verifies.
Exec m_exec
 How gpg is run; replaced by a fake in the unit tests.

Detailed Description

The detached signature on a store's .gpg-id: whether the configured signing key is usable, signing the file, and checking that an existing .gpg-id.sig was made by one of the configured keys.

Every gpg run goes through the Exec given at construction, so the re-encryption worker can hand in its cancellable runner and tests a fake. With no signing keys configured signing is off and verification passes: pass itself only checks signatures when PASSWORD_STORE_SIGNING_KEY is set.

Definition at line 28 of file gpgidsigner.h.

Member Typedef Documentation

◆ Exec

Initial value:
std::function<int(const QString &app, const QStringList &args,
const QString &input, QString *out, QString *err)>

Blocking process runner: Executor::executeBlocking()'s shape.

Returns
The exit code, or -1 when the process could not run.

Definition at line 41 of file gpgidsigner.h.

Constructor & Destructor Documentation

◆ GpgIdSigner()

GpgIdSigner::GpgIdSigner ( QString gpgExecutable,
QStringList signingKeys,
Exec exec = Exec() )

Create a signer.

Parameters
gpgExecutableThe gpg binary; a wsl prefix routes file paths through wslpath.
signingKeysFull fingerprints from the settings (40 hex characters for v4 keys, 64 for v5/v6), as pass's PASSWORD_STORE_SIGNING_KEY requires: gpg reports fingerprints in its KEY_CONSIDERED and VALIDSIG status lines, so a short key ID would never pass haveSecretKey() or verify(). The first one signs, any of them verifies.
execProcess runner; Executor::executeBlocking() when empty.

Definition at line 19 of file gpgidsigner.cpp.

Here is the call graph for this function:

Member Function Documentation

◆ enabled()

auto GpgIdSigner::enabled ( ) const -> bool
inline

Whether any signing key is configured at all.

Returns
true when sign() will do something.

Definition at line 72 of file gpgidsigner.h.

Here is the caller graph for this function:

◆ haveSecretKey()

auto GpgIdSigner::haveSecretKey ( ) const -> bool

Whether gpg has the secret key that sign() will use, i.e. the first configured key.

Returns
true when signing can work; false when no key is configured.

Definition at line 47 of file gpgidsigner.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ keys()

auto GpgIdSigner::keys ( ) const -> const QStringList &
inline

The keys this signer was given.

Returns
The list from the constructor.

Definition at line 78 of file gpgidsigner.h.

Here is the caller graph for this function:

◆ keysFromSetting()

auto GpgIdSigner::keysFromSetting ( const QString & passSigningKey) -> QStringList
static

Split the settings value into keys, upper-cased the way gpg prints fingerprints.

Parameters
passSigningKeyThe space-separated setting.
Returns
The keys, without empties.

Definition at line 31 of file gpgidsigner.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

auto GpgIdSigner::run ( const QStringList & args,
QString * out = nullptr,
QString * err = nullptr,
const QString & input = QString() ) const -> int
private

Run gpg with args through m_exec.

Parameters
argsArguments for gpg.
outIf non-null, receives stdout.
errIf non-null, receives stderr.
inputData for gpg's stdin; empty for none.
Returns
gpg's exit code.

Definition at line 42 of file gpgidsigner.cpp.

Here is the caller graph for this function:

◆ sign()

auto GpgIdSigner::sign ( const QString & gpgIdFile,
const QByteArray & contents,
QString * error = nullptr ) const -> bool

Write <file>.sig, a detached signature by the first key over contents, the bytes the caller just wrote as gpgIdFile.

gpg signs what it is fed on stdin, not what is under the file's name by the time it reads it (a co-writer of the store could have swapped the list between the write and the signing, and the user's key would have vouched for theirs), and writes the signature into a directory of QtPass's own; the signature then goes next to the list through Util::writeFileReplacing(), never by opening the .sig name.

Only the first key signs, as --local-user: gpg then fails when that secret key is missing, where --default-key would quietly sign with another one. The new signature is verified against contents the way verify() does before it is placed; one that is not by a configured key is not written.

Parameters
gpgIdFileThe .gpg-id the signature is for; <gpgIdFile>.sig is written.
contentsThe exact bytes of that file, as written. UTF-8 text, as a recipient list is; anything else is refused, as verify() refuses it.
errorReceives gpg's stderr, or the reason, when it fails.
Returns
true when the signature is in place and verified. Does nothing and returns true when no key is configured.

Definition at line 65 of file gpgidsigner.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ validSigFingerprints()

auto GpgIdSigner::validSigFingerprints ( const QString & statusOutput) -> QStringList
static

Pick the fingerprints out of gpg's --status-fd VALIDSIG line.

Parameters
statusOutputgpg's status output.
Returns
The signing key's fingerprint and the primary key's fingerprint, or an empty list when there is no VALIDSIG, or when gpg says the key that made that signature is revoked (REVKEYSIG, KEYREVOKED).

Definition at line 125 of file gpgidsigner.cpp.

Here is the caller graph for this function:

◆ verify()

auto GpgIdSigner::verify ( const QByteArray & contents,
const QString & signatureFile ) const -> bool

Check a detached signature against the given bytes: gpg must report a VALIDSIG whose key or primary-key fingerprint is one of the configured keys.

The data goes to gpg on stdin, so the caller verifies exactly the bytes it is about to use as the recipient list; verifying a path and reading it again afterwards would let anyone who can write to the store swap the file in between (#1842).

Parameters
contentsThe .gpg-id bytes.
signatureFileThe .gpg-id.sig next to it.
Returns
true when the signature is good, or when no key is configured.

Definition at line 160 of file gpgidsigner.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ verifyFile()

auto GpgIdSigner::verifyFile ( const QString & gpgIdFile,
QByteArray * contents ) const -> bool

Read gpgIdFile and verify it against <file>.sig.

Parameters
gpgIdFileThe .gpg-id.
contentsReceives the bytes that were verified, so the caller can parse those and nothing else.
Returns
true when the signature is good, or when no key is configured. false when the file cannot be read.

Definition at line 215 of file gpgidsigner.cpp.

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ kMaxSignatureBytes

qint64 GpgIdSigner::kMaxSignatureBytes = 64 * 1024
staticconstexpr

Most bytes of a .gpg-id.sig verify() hands to gpg.

A detached signature is well under a KiB; far beyond any real one.

Definition at line 35 of file gpgidsigner.h.

◆ m_exec

Exec GpgIdSigner::m_exec
private

How gpg is run; replaced by a fake in the unit tests.

Definition at line 159 of file gpgidsigner.h.

◆ m_gpg

QString GpgIdSigner::m_gpg
private

The gpg executable, as configured.

Definition at line 152 of file gpgidsigner.h.

◆ m_keys

QStringList GpgIdSigner::m_keys
private

The configured signing keys. The first one signs; a signature by any of them verifies.

Definition at line 157 of file gpgidsigner.h.


The documentation for this class was generated from the following files: