|
QtPass 2.0.0
Developer documentation
|
OpenPGP encryption and decryption in-process, through RNP. More...
#include <rnpcrypto.h>
Classes | |
| struct | KeyInfo |
| One primary key in the keyring, as the Users dialog lists keys. More... | |
Public Types | |
| using | PassphraseProvider = std::function<QString(const QString &keyId)> |
| Asks for the passphrase of a secret key. | |
Public Member Functions | |
| RnpCrypto () | |
| Creates an empty keyring. | |
| ~RnpCrypto () | |
| Frees the keyring and everything RNP holds for it. | |
| RnpCrypto (const RnpCrypto &)=delete | |
| auto | operator= (const RnpCrypto &) -> RnpCrypto &=delete |
| RnpCrypto (RnpCrypto &&)=delete | |
| auto | operator= (RnpCrypto &&) -> RnpCrypto &=delete |
| auto | isValid () const -> bool |
| Whether the RNP context could be created at all. | |
| auto | importKeys (const QByteArray &keyData, QString *error=nullptr) -> QStringList |
| Imports public and secret keys from armored or binary key data. | |
| void | setPassphraseProvider (PassphraseProvider provider) |
| Sets how secret-key passphrases are obtained. | |
| void | setMaxPlaintextBytes (qint64 bytes) |
| Sets the most bytes of plaintext decrypt() may produce. | |
| auto | encrypt (const QByteArray &plaintext, const QStringList &recipients, QString *error=nullptr) -> QByteArray |
Encrypts plaintext to every recipient, as one message. | |
| auto | decrypt (const QByteArray &ciphertext, QString *error=nullptr, bool *ok=nullptr) -> QByteArray |
| Decrypts an OpenPGP message with any secret key in the keyring. | |
| auto | listKeys (bool secretOnly=false) const -> QList< KeyInfo > |
| The primary keys in the keyring. | |
| auto | sign (const QByteArray &data, const QString &signer, QString *error=nullptr) -> QByteArray |
Makes a detached signature over data, as gpg –detach-sign –local-user signer does (for .gpg-id.sig). | |
| auto | verify (const QByteArray &data, const QByteArray &signature, QString *error=nullptr) -> QStringList |
Checks a detached signature over data, as QtPass reads gpg's VALIDSIG. | |
| auto | protectKey (const QString &fingerprint, const QString &passphrase, QString *error=nullptr) -> bool |
Protects the secret parts of a key with passphrase. | |
| auto | saveKeyring (const QString &dir, bool allowUnprotected=false, QString *error=nullptr) const -> bool |
Writes the keyring to dir: keyring.gpg, public and secret keys in one file (OpenPGP keys, as GnuPG 1 kept them), owner-only and replaced whole, so a reader sees the old keyring or the new one. | |
| auto | loadKeyring (const QString &dir, QString *error=nullptr) -> bool |
Adds the keyring in dir (as saveKeyring() wrote it) to this one. Secret keys stay protected until an operation needs them. | |
Static Public Attributes | |
| static constexpr qint64 | kMaxPlaintextBytes = 64LL * 1024 * 1024 |
| Most bytes of plaintext decrypt() produces by default. | |
| static constexpr qint64 | kMaxKeyringBytes = 64LL * 1024 * 1024 |
| Most bytes of a keyring file: saveKeyring() writes no larger one, loadKeyring() reads no larger one. | |
Private Attributes | |
| rnp_ffi_st * | m_ffi = nullptr |
| RNP's handle holding this object's keyring; null when RNP could not be initialised, and every operation then fails with an error. | |
| PassphraseProvider | m_passphrase |
| Asked for the passphrase of a locked secret key during decryption; set with setPassphraseProvider(), empty for none. | |
| qint64 | m_maxPlaintext = kMaxPlaintextBytes |
| Largest plaintext decrypt() returns, in bytes. | |
OpenPGP encryption and decryption in-process, through RNP.
A spike towards a backend that needs no gpg, git or pass binary (#2005): the same work ImitatePass hands to gpg, done by the RNP library (the OpenPGP code Thunderbird uses). Keys live in this object's own keyring, filled from armored exports (gpg –export / –export-secret-keys); it never reads or writes ~/.gnupg. Built only with CONFIG+=rnp.
Output is binary OpenPGP, as pass and QtPass write .gpg files. Every call reports failure through its return value and a human-readable error.
Security trade-off (SECURITY.md, "In-process OpenPGP"): with gpg, QtPass never holds a secret key; gpg-agent does, or a smartcard. Here the secret key is imported into this process and, while a message is decrypted, the unlocked key and the passphrase are in its memory. Imported keys keep their own passphrase protection; no smartcard support. A mode built on this must be chosen deliberately, never used as a silent fallback for a missing gpg.
Definition at line 41 of file rnpcrypto.h.
| using RnpCrypto::PassphraseProvider = std::function<QString(const QString &keyId)> |
Asks for the passphrase of a secret key.
Called with the key's 16-hex-digit key ID; return an empty string to give up.
Definition at line 86 of file rnpcrypto.h.
| RnpCrypto::RnpCrypto | ( | ) |
Creates an empty keyring.
Definition at line 504 of file rnpcrypto.cpp.
| RnpCrypto::~RnpCrypto | ( | ) |
Frees the keyring and everything RNP holds for it.
Definition at line 512 of file rnpcrypto.cpp.
| auto RnpCrypto::decrypt | ( | const QByteArray & | ciphertext, |
| QString * | error = nullptr, | ||
| bool * | ok = nullptr ) -> QByteArray |
Decrypts an OpenPGP message with any secret key in the keyring.
Only an integrity-protected message is accepted (SEIPD with MDC, or AEAD such as the OCB packets GnuPG 2.4 writes): one without (CFB with no MDC, the EFAIL kind) is refused, as GnuPG has since 2.2.8. A plaintext over the limit (setMaxPlaintextBytes()) fails too.
| ciphertext | Binary or armored OpenPGP message. |
| error | Set to the reason when decryption fails. |
| ok | Set to whether decryption succeeded, since an entry can be empty. |
Definition at line 640 of file rnpcrypto.cpp.
| auto RnpCrypto::encrypt | ( | const QByteArray & | plaintext, |
| const QStringList & | recipients, | ||
| QString * | error = nullptr ) -> QByteArray |
Encrypts plaintext to every recipient, as one message.
| plaintext | The entry's content. |
| recipients | As a .gpg-id lists them, in the forms gpg -r takes: a fingerprint (40 or 64 hex digits, blanks allowed), a long or short (8 hex digits) key ID with or without 0x, an e-mail address (the key with a user ID of that address, any case; stricter than gpg's substring search; a user ID with no address in angle brackets must then be just the address, so "alice@example.org (work)" is not found by its address), or a whole user ID or part of one. Revoked user IDs, and ones without a valid self-signature, name nothing. Each must name exactly one key that can encrypt (not expired or revoked, with a usable encryption key); an empty recipient is an error. |
| error | Set to the reason when encryption fails, naming the first recipient that has no usable key or names more than one. |
Definition at line 586 of file rnpcrypto.cpp.
| auto RnpCrypto::importKeys | ( | const QByteArray & | keyData, |
| QString * | error = nullptr ) -> QStringList |
Imports public and secret keys from armored or binary key data.
| keyData | Output of gpg –export or –export-secret-keys. |
| error | Set to the reason when the import fails. |
Definition at line 535 of file rnpcrypto.cpp.
|
nodiscard |
Whether the RNP context could be created at all.
Definition at line 518 of file rnpcrypto.cpp.
|
nodiscard |
The primary keys in the keyring.
| secretOnly | Only keys with a secret part here. |
Definition at line 785 of file rnpcrypto.cpp.
| auto RnpCrypto::loadKeyring | ( | const QString & | dir, |
| QString * | error = nullptr ) -> bool |
Adds the keyring in dir (as saveKeyring() wrote it) to this one. Secret keys stay protected until an operation needs them.
keyring.gpg is read as a regular file, not through a link (nor is dir itself a link or junction; its parents are as configured), and only up to kMaxKeyringBytes. A missing or empty file is an empty keyring, not an error.
| dir | The keyring folder. |
| error | Set to the reason when loading fails. |
Definition at line 1100 of file rnpcrypto.cpp.
| auto RnpCrypto::protectKey | ( | const QString & | fingerprint, |
| const QString & | passphrase, | ||
| QString * | error = nullptr ) -> bool |
Protects the secret parts of a key with passphrase.
For a key imported without protection: saveKeyring() keeps secret keys on disk only protected by their own passphrase. Only the parts not yet protected get passphrase, so a key left half protected can be finished; the others keep theirs (no passphrase is changed here). A key all of whose secret parts are protected already is an error. The UTF-8 copy made here is wiped afterwards; passphrase itself, and any copy the caller holds, is the caller's to wipe.
| fingerprint | The primary key's fingerprint. |
| passphrase | The passphrase; not empty. |
| error | Set to the reason when not every part ended up protected. |
Definition at line 950 of file rnpcrypto.cpp.
| auto RnpCrypto::saveKeyring | ( | const QString & | dir, |
| bool | allowUnprotected = false, | ||
| QString * | error = nullptr ) const -> bool |
Writes the keyring to dir: keyring.gpg, public and secret keys in one file (OpenPGP keys, as GnuPG 1 kept them), owner-only and replaced whole, so a reader sees the old keyring or the new one.
The file holds exactly this keyring afterwards: load the folder first (loadKeyring()), or every key on disk that is not in this keyring is gone. That is how a removed key disappears from disk.
Secret keys are written as they are held: protected by their own passphrase, never decrypted for this. A secret key without protection is refused (nothing is written) unless allowUnprotected, the user's explicit consent; protectKey() first is the other way. So is a secret part whose protection RNP cannot name.
| dir | The keyring folder, created owner-only if missing (on Windows: as private as the user profile it is in); QtPass's own, never ~/.gnupg, and not a link or junction (the folder itself; its parents are as configured). |
| allowUnprotected | Write unprotected secret keys as well. |
| error | Set to the reason when nothing was written, naming the first unprotected key. |
Definition at line 1009 of file rnpcrypto.cpp.
| void RnpCrypto::setMaxPlaintextBytes | ( | qint64 | bytes | ) |
Sets the most bytes of plaintext decrypt() may produce.
| bytes | The limit; kMaxPlaintextBytes until set. A value that is not positive is ignored and the limit stays as it was: there is no "unlimited". A value above 4 GiB - 1 is capped to 4 GiB - 1, as RNP keeps the limit in 32 bits. |
Definition at line 520 of file rnpcrypto.cpp.
| void RnpCrypto::setPassphraseProvider | ( | PassphraseProvider | provider | ) |
Sets how secret-key passphrases are obtained.
| provider | Called when decryption needs a locked key. |
Definition at line 531 of file rnpcrypto.cpp.
| auto RnpCrypto::sign | ( | const QByteArray & | data, |
| const QString & | signer, | ||
| QString * | error = nullptr ) -> QByteArray |
Makes a detached signature over data, as gpg –detach-sign –local-user signer does (for .gpg-id.sig).
| data | The bytes signed, a .gpg-id as written. |
| signer | The key: a fingerprint or key ID names exactly that key; an e-mail address the key with a user ID of that address (any case); else a user ID, whole or in part. It must name exactly one key that can sign and whose secret key is here; that key is used, not another. |
| error | Set to the reason when signing fails. |
Definition at line 845 of file rnpcrypto.cpp.
| auto RnpCrypto::verify | ( | const QByteArray & | data, |
| const QByteArray & | signature, | ||
| QString * | error = nullptr ) -> QStringList |
Checks a detached signature over data, as QtPass reads gpg's VALIDSIG.
The first signature that verifies decides. A signature by a key that is now revoked (or whose primary is) counts for nothing, as with GnuPG in GpgIdSigner; one by a key that has since expired still counts, as gpg calls it a good signature.
| data | The signed bytes. |
| signature | Binary or armored detached signature. |
| error | Set to the reason when no signature counts. |
Definition at line 897 of file rnpcrypto.cpp.
|
staticconstexpr |
Most bytes of a keyring file: saveKeyring() writes no larger one, loadKeyring() reads no larger one.
Far beyond a keyring of a few hundred keys; a file larger than this is not read at all.
Definition at line 104 of file rnpcrypto.h.
|
staticconstexpr |
Most bytes of plaintext decrypt() produces by default.
An OpenPGP message is compressed, so a small entry in a shared store can decompress to gigabytes; decrypt() fails at this many instead of filling memory. The same limit QtPass gives gpg (–max-output).
Definition at line 95 of file rnpcrypto.h.
|
private |
RNP's handle holding this object's keyring; null when RNP could not be initialised, and every operation then fails with an error.
Definition at line 290 of file rnpcrypto.h.
|
private |
Largest plaintext decrypt() returns, in bytes.
Definition at line 297 of file rnpcrypto.h.
|
private |
Asked for the passphrase of a locked secret key during decryption; set with setPassphraseProvider(), empty for none.
Definition at line 295 of file rnpcrypto.h.