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}
Type type(const QSqlDatabase &db)
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 left(qsizetype n) const const
QString mid(qsizetype position, qsizetype n) 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-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:56:14 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.