QtPass 1.6.0
Multi-platform GUI for pass, the standard unix password manager.
Loading...
Searching...
No Matches
gpgkeystate.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2// SPDX-License-Identifier: GPL-3.0-or-later
3#include "gpgkeystate.h"
4#include "gpgkeystate_p.h"
5
6#include "util.h"
7
8#include <QRegularExpression>
9
10constexpr int GPG_MIN_FIELDS = 10;
11constexpr int GPG_FIELD_VALIDITY = 1;
12constexpr int GPG_FIELD_KEY_ID = 4;
13constexpr int GPG_FIELD_CREATED = 5;
14constexpr int GPG_FIELD_EXPIRY = 6;
15constexpr int GPG_FIELD_USERID = 9;
16
23auto classifyRecord(const QString &record_type) -> GpgRecordType {
24 if (record_type == "pub") {
25 return GpgRecordType::Pub;
26 }
27 if (record_type == "sec") {
28 return GpgRecordType::Sec;
29 }
30 if (record_type == "uid") {
31 return GpgRecordType::Uid;
32 }
33 if (record_type == "fpr") {
34 return GpgRecordType::Fpr;
35 }
36 if (record_type == "sub") {
37 return GpgRecordType::Sub;
38 }
39 if (record_type == "ssb") {
40 return GpgRecordType::Ssb;
41 }
42 if (record_type == "grp") {
43 return GpgRecordType::Grp;
44 }
46}
47
54void handlePubSecRecord(const QStringList &props, bool secret,
55 UserInfo &current_user) {
56 if (props.size() < GPG_MIN_FIELDS) {
57 return;
58 }
59 current_user.key_id = props[GPG_FIELD_KEY_ID];
60 current_user.name = props[GPG_FIELD_USERID];
61 if (!props[GPG_FIELD_VALIDITY].isEmpty()) {
62 current_user.validity = props[GPG_FIELD_VALIDITY][0].toLatin1();
63 }
64
65 bool okCreated = false;
66 const qint64 createdSecs = props[GPG_FIELD_CREATED].toLongLong(&okCreated);
67 if (okCreated) {
68 current_user.created.setSecsSinceEpoch(createdSecs);
69 }
70
71 bool okExpiry = false;
72 const qint64 expirySecs = props[GPG_FIELD_EXPIRY].toLongLong(&okExpiry);
73 if (okExpiry) {
74 current_user.expiry.setSecsSinceEpoch(expirySecs);
75 }
76
77 current_user.have_secret = secret;
78}
79
85void handleUidRecord(const QStringList &props, UserInfo &current_user) {
86 current_user.name = props[GPG_FIELD_USERID];
87}
88
94void handleFprRecord(const QStringList &props, UserInfo &current_user) {
95 if (props.size() < GPG_MIN_FIELDS) {
96 return;
97 }
98 if (!current_user.key_id.isEmpty() &&
99 props[GPG_FIELD_USERID].endsWith(current_user.key_id)) {
100 current_user.key_id = props[GPG_FIELD_USERID];
101 }
102}
103
110auto parseGpgColonOutput(const QString &output, bool secret)
111 -> QList<UserInfo> {
112 QList<UserInfo> users;
113
114#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
115 const QStringList lines =
116 output.split(Util::newLinesRegex(), Qt::SkipEmptyParts);
117#else
118 const QStringList lines =
119 output.split(Util::newLinesRegex(), QString::SkipEmptyParts);
120#endif
121
122 UserInfo current_user;
123
124 for (const QString &key : lines) {
125 QStringList props = key.split(':');
126 if (props.size() < GPG_MIN_FIELDS) {
127 continue;
128 }
129
130 const QString record_type = props[0];
131 const GpgRecordType type = classifyRecord(record_type);
132
133 switch (type) {
136 if (!current_user.key_id.isEmpty()) {
137 users.append(current_user);
138 }
139 current_user = UserInfo();
140 handlePubSecRecord(props, secret && (type == GpgRecordType::Sec),
141 current_user);
142 break;
144 if (current_user.name.isEmpty()) {
145 handleUidRecord(props, current_user);
146 }
147 break;
149 handleFprRecord(props, current_user);
150 break;
151 default:
152 break;
153 }
154 }
155
156 if (!current_user.key_id.isEmpty()) {
157 users.append(current_user);
158 }
159
160 return users;
161}
static auto newLinesRegex() -> const QRegularExpression &
Returns a regex to match newline characters.
Definition util.cpp:272
void handlePubSecRecord(const QStringList &props, bool secret, UserInfo &current_user)
Handle a pub or sec record in GPG colon output.
auto parseGpgColonOutput(const QString &output, bool secret) -> QList< UserInfo >
Parse GPG –with-colons output into a list of UserInfo.
constexpr int GPG_FIELD_KEY_ID
constexpr int GPG_FIELD_VALIDITY
constexpr int GPG_FIELD_EXPIRY
constexpr int GPG_FIELD_CREATED
constexpr int GPG_MIN_FIELDS
auto classifyRecord(const QString &record_type) -> GpgRecordType
Classify a GPG colon output record type.
void handleFprRecord(const QStringList &props, UserInfo &current_user)
Handle an fpr (fingerprint) record in GPG colon output.
void handleUidRecord(const QStringList &props, UserInfo &current_user)
Handle a uid record in GPG colon output.
constexpr int GPG_FIELD_USERID
GpgRecordType
Definition gpgkeystate.h:12
Stores key info lines including validity, creation date and more.
Definition userinfo.h:13
bool have_secret
UserInfo::have_secret whether secret key is available (can decrypt with this key).
Definition userinfo.h:51
QString key_id
UserInfo::key_id hexadecimal representation of the GnuPG key identifier.
Definition userinfo.h:41
QDateTime created
UserInfo::created date/time when key was created.
Definition userinfo.h:66
QString name
UserInfo::name GPG user ID / full name.
Definition userinfo.h:36
char validity
UserInfo::validity GnuPG representation of validity http://git.gnupg.org/cgi-bin/gitweb....
Definition userinfo.h:46
QDateTime expiry
UserInfo::expiry date/time when key expires.
Definition userinfo.h:62