Libkleo

keyparameters.cpp
1/* -*- mode: c++; c-basic-offset:4 -*-
2 utils/keyparameters.cpp
3
4 This file is part of Libkleo
5 SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
6
7 SPDX-FileCopyrightText: 2020, 2022 g10 Code GmbH
8 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
9
10 SPDX-License-Identifier: GPL-2.0-or-later
11*/
12
13#include "keyparameters.h"
14
15#include <Libkleo/KeyUsage>
16
17#include <QDate>
18#include <QUrl>
19
20#include "libkleo_debug.h"
21
22using namespace Kleo;
23using namespace GpgME;
24using namespace Qt::StringLiterals;
25
26namespace
27{
28QString encodeDomainName(const QString &domain)
29{
30 const QByteArray encodedDomain = QUrl::toAce(domain);
31 return encodedDomain.isEmpty() ? domain : QString::fromLatin1(encodedDomain);
32}
33
34QString encodeEmail(const QString &email)
35{
36 const int at = email.lastIndexOf(QLatin1Char('@'));
37 if (at < 0) {
38 return email;
39 }
40 return email.left(at + 1) + encodeDomainName(email.mid(at + 1));
41}
42}
43
44class KeyParameters::Private
45{
46 friend class ::Kleo::KeyParameters;
47
48 Protocol protocol;
49
50 Subkey::PubkeyAlgo keyType = Subkey::AlgoUnknown;
51 QString cardKeyRef;
52 unsigned int keyLength = 0;
53 QString keyCurve;
54 KeyUsage keyUsage;
55
56 Subkey::PubkeyAlgo subkeyType = Subkey::AlgoUnknown;
57 unsigned int subkeyLength = 0;
58 QString subkeyCurve;
59 KeyUsage subkeyUsage;
60
61 QString name;
62 QString comment;
63 QString dn;
64 std::vector<QString> emailAdresses;
65 std::vector<QString> domainNames;
66 std::vector<QString> uris;
67 QString serial;
68 QString signingKey;
69
70 QDate expirationDate;
71
72 QString issuerDN;
73
74public:
75 explicit Private(Protocol proto)
76 : protocol(proto)
77 {
78 }
79};
80
81KeyParameters::KeyParameters()
82 : KeyParameters{NoProtocol}
83{
84}
85
86KeyParameters::KeyParameters(Protocol protocol)
87 : d{new Private{protocol}}
88{
89}
90
91KeyParameters::~KeyParameters() = default;
92
93KeyParameters::KeyParameters(const KeyParameters &other)
94 : d{new Private{*other.d}}
95{
96}
97
98KeyParameters &KeyParameters::operator=(const KeyParameters &other)
99{
100 *d = *other.d;
101 return *this;
102}
103
104KeyParameters::KeyParameters(KeyParameters &&other) = default;
105
106KeyParameters &KeyParameters::operator=(KeyParameters &&other) = default;
107
108KeyParameters::Protocol KeyParameters::protocol() const
109{
110 return d->protocol;
111}
112
113void KeyParameters::setKeyType(Subkey::PubkeyAlgo type)
114{
115 d->keyType = type;
116}
117
118GpgME::Subkey::PubkeyAlgo KeyParameters::keyType() const
119{
120 return d->keyType;
121}
122
123void KeyParameters::setCardKeyRef(const QString &cardKeyRef)
124{
125 d->cardKeyRef = cardKeyRef;
126}
127
128QString KeyParameters::cardKeyRef() const
129{
130 return d->cardKeyRef;
131}
132
133void KeyParameters::setKeyLength(unsigned int length)
134{
135 d->keyLength = length;
136}
137
138unsigned int KeyParameters::keyLength() const
139{
140 return d->keyLength;
141}
142
143void KeyParameters::setKeyCurve(const QString &curve)
144{
145 d->keyCurve = curve;
146}
147
148QString KeyParameters::keyCurve() const
149{
150 return d->keyCurve;
151}
152
153void KeyParameters::setKeyUsage(const KeyUsage &usage)
154{
155 d->keyUsage = usage;
156}
157
158KeyUsage KeyParameters::keyUsage() const
159{
160 return d->keyUsage;
161}
162
163void KeyParameters::setSubkeyType(Subkey::PubkeyAlgo type)
164{
165 d->subkeyType = type;
166}
167
168Subkey::PubkeyAlgo KeyParameters::subkeyType() const
169{
170 return d->subkeyType;
171}
172
173void KeyParameters::setSubkeyLength(unsigned int length)
174{
175 d->subkeyLength = length;
176}
177
178unsigned int KeyParameters::subkeyLength() const
179{
180 return d->subkeyLength;
181}
182
183void KeyParameters::setSubkeyCurve(const QString &curve)
184{
185 d->subkeyCurve = curve;
186}
187
188QString KeyParameters::subkeyCurve() const
189{
190 return d->subkeyCurve;
191}
192
193void KeyParameters::setSubkeyUsage(const KeyUsage &usage)
194{
195 d->subkeyUsage = usage;
196}
197
198KeyUsage KeyParameters::subkeyUsage() const
199{
200 return d->subkeyUsage;
201}
202
203void KeyParameters::setExpirationDate(const QDate &date)
204{
205 d->expirationDate = date;
206}
207
208QDate KeyParameters::expirationDate() const
209{
210 return d->expirationDate;
211}
212
213void KeyParameters::setName(const QString &name)
214{
215 d->name = name;
216}
217
218QString KeyParameters::name() const
219{
220 return d->name;
221}
222
223void KeyParameters::setComment(const QString &comment)
224{
225 d->comment = comment;
226}
227
228QString KeyParameters::comment() const
229{
230 return d->comment;
231}
232
233void KeyParameters::setDN(const QString &dn)
234{
235 d->dn = dn;
236}
237
238QString KeyParameters::dn() const
239{
240 return d->dn;
241}
242
243void KeyParameters::setEmail(const QString &email)
244{
245 d->emailAdresses = {email};
246}
247
248void KeyParameters::addEmail(const QString &email)
249{
250 d->emailAdresses.push_back(email);
251}
252
253std::vector<QString> KeyParameters::emails() const
254{
255 return d->emailAdresses;
256}
257
258void KeyParameters::addDomainName(const QString &domain)
259{
260 d->domainNames.push_back(domain);
261}
262
263std::vector<QString> KeyParameters::domainNames() const
264{
265 return d->domainNames;
266}
267
268void KeyParameters::addURI(const QString &uri)
269{
270 d->uris.push_back(uri);
271}
272
273std::vector<QString> KeyParameters::uris() const
274{
275 return d->uris;
276}
277
278QString KeyParameters::serial() const
279{
280 return d->serial;
281}
282
283void KeyParameters::setSerial(const QString &serial)
284{
285 d->serial = serial;
286}
287
288void KeyParameters::setUseRandomSerial()
289{
290 d->serial = u"random"_s;
291}
292
293QString KeyParameters::issuerDN() const
294{
295 return d->issuerDN;
296}
297
298void KeyParameters::setIssuerDN(const QString &issuerDN)
299{
300 d->issuerDN = issuerDN;
301}
302
303QString KeyParameters::signingKey() const
304{
305 return d->signingKey;
306}
307
308void KeyParameters::setSigningKey(const QString &signingKey)
309{
310 d->signingKey = signingKey;
311}
312
313namespace
314{
315QString serialize(Subkey::PubkeyAlgo algo)
316{
317 return QString::fromLatin1(Subkey::publicKeyAlgorithmAsString(algo));
318}
319
320QString serialize(unsigned int number)
321{
322 return QString::number(number);
323}
324
325QString serialize(KeyUsage keyUsage)
326{
327 QStringList usages;
328 if (keyUsage.canSign()) {
329 usages << QStringLiteral("sign");
330 }
331 if (keyUsage.canEncrypt()) {
332 usages << QStringLiteral("encrypt");
333 }
334 if (keyUsage.canAuthenticate()) {
335 usages << QStringLiteral("auth");
336 }
337 if (keyUsage.canCertify()) {
338 usages << QStringLiteral("cert");
339 }
340 return usages.join(QLatin1Char{' '});
341}
342
343QString serialize(const QDate &date)
344{
345 return date.toString(Qt::ISODate);
346}
347
348QString serialize(const char *key, const QString &value)
349{
350 return QString::fromLatin1(key) + QLatin1Char(':') + value;
351}
352}
353
354QString KeyParameters::toString() const
355{
356 QStringList keyParameters;
357
358 keyParameters.push_back(QLatin1StringView("<GnupgKeyParms format=\"internal\">"));
359
360 if (d->protocol == OpenPGP) {
361 // for backward compatibility with GnuPG 2.0 and earlier
362 keyParameters.push_back(QStringLiteral("%ask-passphrase"));
363 }
364
365 // add Key-Type as first parameter
366 if (!d->cardKeyRef.isEmpty()) {
367 keyParameters.push_back(serialize("Key-Type", QLatin1StringView{"card:"} + d->cardKeyRef));
368 } else if (d->keyType != Subkey::AlgoUnknown) {
369 keyParameters.push_back(serialize("Key-Type", serialize(d->keyType)));
370 } else {
371 qCWarning(LIBKLEO_LOG) << "KeyParameters::toString(): Key type is unset/empty";
372 }
373 if (d->keyLength) {
374 keyParameters.push_back(serialize("Key-Length", serialize(d->keyLength)));
375 }
376 if (!d->keyCurve.isEmpty()) {
377 keyParameters.push_back(serialize("Key-Curve", d->keyCurve));
378 }
379 keyParameters.push_back(serialize("Key-Usage", serialize(d->keyUsage)));
380
381 if (d->subkeyType != Subkey::AlgoUnknown) {
382 keyParameters.push_back(serialize("Subkey-Type", serialize(d->subkeyType)));
383 if (d->subkeyUsage.value()) {
384 keyParameters.push_back(serialize("Subkey-Usage", serialize(d->subkeyUsage)));
385 }
386 if (d->subkeyLength) {
387 keyParameters.push_back(serialize("Subkey-Length", serialize(d->subkeyLength)));
388 }
389 if (!d->subkeyCurve.isEmpty()) {
390 keyParameters.push_back(serialize("Subkey-Curve", d->subkeyCurve));
391 }
392 }
393
394 if (d->expirationDate.isValid()) {
395 keyParameters.push_back(serialize("Expire-Date", serialize(d->expirationDate)));
396 }
397
398 if (!d->serial.isEmpty()) {
399 keyParameters.push_back(serialize("Serial", d->serial));
400 }
401
402 if (!d->issuerDN.isEmpty()) {
403 keyParameters.push_back(serialize("Issuer-DN", d->issuerDN));
404 }
405
406 if (!d->issuerDN.isEmpty()) {
407 keyParameters.push_back(serialize("Signing-Key", d->signingKey));
408 }
409
410 if (!d->name.isEmpty()) {
411 keyParameters.push_back(serialize("Name-Real", d->name));
412 }
413 if (!d->comment.isEmpty()) {
414 keyParameters.push_back(serialize("Name-Comment", d->comment));
415 }
416 if (!d->dn.isEmpty()) {
417 keyParameters.push_back(serialize("Name-DN", d->dn));
418 }
419 std::transform(std::cbegin(d->emailAdresses), std::cend(d->emailAdresses), std::back_inserter(keyParameters), [this](const auto &email) {
420 return serialize("Name-Email", (d->protocol == CMS) ? encodeEmail(email) : email);
421 });
422 std::transform(std::cbegin(d->domainNames), std::cend(d->domainNames), std::back_inserter(keyParameters), [](const auto &domain) {
423 return serialize("Name-DNS", encodeDomainName(domain));
424 });
425 std::transform(std::cbegin(d->uris), std::cend(d->uris), std::back_inserter(keyParameters), [](const auto &uri) {
426 return serialize("Name-URI", uri);
427 });
428
429 keyParameters.push_back(QLatin1StringView("</GnupgKeyParms>"));
430
431 return keyParameters.join(QLatin1Char('\n'));
432}
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
bool isEmpty() const const
QString toString(QStringView format, QCalendar cal) const const
void push_back(parameter_type value)
QString fromLatin1(QByteArrayView str)
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
QString number(double n, char format, int precision)
QString join(QChar separator) const const
QByteArray toAce(const QString &domain, AceProcessingOptions options)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:50:12 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.