10#include "openpgpcertificatecreationdialog.h"
12#include "adjustingscrollarea.h"
13#include "animatedexpander_p.h"
14#include "nameandemailwidget.h"
15#include "openpgpcertificatecreationconfig.h"
16#include "utils/compat.h"
17#include "utils/compliance.h"
18#include "utils/expiration.h"
19#include "utils/gnupg.h"
20#include "utils/keyparameters.h"
21#include "utils/keyusage.h"
23#include <KConfigGroup>
24#include <KDateComboBox>
25#include <KLocalizedString>
28#include <KSharedConfig>
31#include <QDialogButtonBox>
36#include <QGpgME/CryptoConfig>
37#include <QGpgME/Protocol>
39#include "libkleo_debug.h"
43static bool unlimitedValidityIsAllowed()
45 return !Kleo::Expiration::maximumExpirationDate().
isValid();
48class OpenPGPCertificateCreationDialog::Private
50 friend class ::Kleo::OpenPGPCertificateCreationDialog;
64 AnimatedExpander *expander;
70 infoLabel =
new QLabel{dialog};
72 mainLayout->addWidget(infoLabel);
83 scrollAreaLayout->setContentsMargins(0, 0, 0, 0);
87 scrollAreaLayout->addWidget(nameAndEmail);
89 withPassCheckBox =
new QCheckBox{
i18n(
"Protect the generated key with a passphrase."), dialog};
91 i18n(
"Encrypts the secret key with an unrecoverable passphrase. You will be asked for the passphrase during key generation."));
92 scrollAreaLayout->addWidget(withPassCheckBox);
94 expander =
new AnimatedExpander(
i18n(
"Advanced options"), {}, dialog);
95 scrollAreaLayout->addWidget(expander);
98 expander->setContentLayout(advancedLayout);
100 keyAlgoLabel =
new QLabel(dialog);
101 keyAlgoLabel->
setText(
i18nc(
"The algorithm and strength of encryption key",
"Key Material"));
105 advancedLayout->addWidget(keyAlgoLabel);
109 advancedLayout->addWidget(keyAlgoCB);
116 hbox->addWidget(expiryCB);
118 expiryLabel =
new QLabel{Expiration::validUntilLabel(), dialog};
119 hbox->addWidget(expiryLabel);
122 hbox->addWidget(expiryDE, 1);
124 advancedLayout->addLayout(hbox);
127 scrollAreaLayout->addStretch(1);
129 mainLayout->addWidget(scrollArea);
135 mainLayout->addWidget(buttonBox);
143 , technicalParameters{KeyParameters::OpenPGP}
147 OpenPGPCertificateCreationConfig settings;
148 const auto requiredFields = settings.requiredFields();
152 ui.infoLabel->
setText(nameIsRequired || emailIsRequired
153 ?
i18n(
"Enter a name and an email address to use for the certificate.")
154 :
i18n(
"Enter a name and/or an email address to use for the certificate."));
156 ui.nameAndEmail->setNameIsRequired(nameIsRequired);
157 ui.nameAndEmail->setNameLabel(settings.nameLabel());
158 const auto nameHint = settings.nameHint();
159 ui.nameAndEmail->setNameHint(nameHint.isEmpty() ? settings.namePlaceholder() : nameHint);
160 ui.nameAndEmail->setNamePattern(settings.nameRegex());
161 ui.nameAndEmail->setEmailIsRequired(emailIsRequired);
162 ui.nameAndEmail->setEmailLabel(settings.emailLabel());
163 const auto emailHint = settings.emailHint();
164 ui.nameAndEmail->setEmailHint(emailHint.isEmpty() ? settings.emailPlaceholder() : emailHint);
165 ui.nameAndEmail->setEmailPattern(settings.emailRegex());
167 ui.expander->setVisible(!settings.hideAdvanced());
169 const auto conf = QGpgME::cryptoConfig();
170 const auto entry = getCryptoConfigEntry(conf,
"gpg-agent",
"enforce-passphrase-constraints");
171 if (entry && entry->boolValue()) {
172 qCDebug(LIBKLEO_LOG) <<
"Disabling passphrase check box because of agent config.";
176 ui.withPassCheckBox->
setChecked(settings.withPassphrase());
177 ui.withPassCheckBox->
setEnabled(!settings.isWithPassphraseImmutable());
185 for (
const auto &algorithm : DeVSCompliance::isActive() ? DeVSCompliance::compliantAlgorithms() : availableAlgorithms()) {
188 auto cryptoConfig = QGpgME::cryptoConfig();
190 auto pubkeyEntry = getCryptoConfigEntry(QGpgME::cryptoConfig(),
"gpg",
"default_pubkey_algo");
192 auto algo = pubkeyEntry->stringValue().split(
QLatin1Char(
'/'))[0];
194 algo = QStringLiteral(
"curve25519");
196 algo = QStringLiteral(
"curve448");
198 auto index = ui.keyAlgoCB->
findData(algo);
211 Kleo::Expiration::setUpExpirationDateComboBox(ui.expiryDE);
213 setExpiryDate(defaultExpirationDate(Kleo::Expiration::ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
214 if (unlimitedValidityIsAllowed()) {
222 ui.expiryLabel->setEnabled(checked);
223 ui.expiryDE->setEnabled(checked);
224 if (checked && !ui.expiryDE->isValid()) {
225 setExpiryDate(defaultExpirationDate(Kleo::Expiration::ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
227 updateTechnicalParameters();
230 updateTechnicalParameters();
233 updateTechnicalParameters();
235 updateTechnicalParameters();
236 connect(ui.expander, &AnimatedExpander::startExpanding, q, [
this]() {
237 q->resize(std::max(q->sizeHint().width(), ui.expander->contentWidth()) + 20, q->sizeHint().height() + ui.expander->contentHeight() + 20);
242 void updateTechnicalParameters()
244 technicalParameters = KeyParameters{KeyParameters::OpenPGP};
245 auto keyType = GpgME::Subkey::AlgoUnknown;
246 auto subkeyType = GpgME::Subkey::AlgoUnknown;
247 auto algoString = ui.keyAlgoCB->currentData().toString();
248 if (algoString.startsWith(QStringLiteral(
"rsa"))) {
249 keyType = GpgME::Subkey::AlgoRSA;
250 subkeyType = GpgME::Subkey::AlgoRSA;
251 const auto strength = algoString.mid(3).toInt();
252 technicalParameters.setKeyLength(strength);
253 technicalParameters.setSubkeyLength(strength);
255 keyType = GpgME::Subkey::AlgoEDDSA;
256 subkeyType = GpgME::Subkey::AlgoECDH;
257 if (algoString.endsWith(QStringLiteral(
"25519"))) {
258 technicalParameters.setKeyCurve(QStringLiteral(
"ed25519"));
259 technicalParameters.setSubkeyCurve(QStringLiteral(
"cv25519"));
261 technicalParameters.setKeyCurve(QStringLiteral(
"ed448"));
262 technicalParameters.setSubkeyCurve(QStringLiteral(
"cv448"));
265 keyType = GpgME::Subkey::AlgoECDSA;
266 subkeyType = GpgME::Subkey::AlgoECDH;
267 technicalParameters.setKeyCurve(algoString);
268 technicalParameters.setSubkeyCurve(algoString);
270 technicalParameters.setKeyType(keyType);
271 technicalParameters.setSubkeyType(subkeyType);
273 technicalParameters.setKeyUsage(KeyUsage(KeyUsage::Certify | KeyUsage::Sign));
274 technicalParameters.setSubkeyUsage(KeyUsage(KeyUsage::Encrypt));
276 technicalParameters.setExpirationDate(expiryDate());
280 QDate expiryDate()
const
282 return ui.expiryCB->isChecked() ? ui.expiryDE->date() :
QDate{};
285 void setTechnicalParameters(
const KeyParameters ¶meters)
288 if (parameters.keyType() == GpgME::Subkey::AlgoRSA_S) {
289 index = ui.keyAlgoCB->findData(QStringLiteral(
"rsa%1").arg(parameters.keyLength()));
291 index = ui.keyAlgoCB->findData(parameters.keyCurve());
293 ui.keyAlgoCB->setCurrentIndex(index);
294 setExpiryDate(parameters.expirationDate());
300 if (ui.nameAndEmail->userID().isEmpty() && !ui.nameAndEmail->nameIsRequired() && !ui.nameAndEmail->emailIsRequired()) {
303 const auto nameError = ui.nameAndEmail->nameError();
304 if (!nameError.isEmpty()) {
307 const auto emailError = ui.nameAndEmail->emailError();
308 if (!emailError.isEmpty()) {
311 if (!Expiration::isValidExpirationDate(expiryDate())) {
312 errors.
push_back(Expiration::validityPeriodHint());
314 if (errors.
size() > 1) {
316 }
else if (!errors.
empty()) {
323 QDate forceDateIntoAllowedRange(
QDate date)
const
325 const auto minDate = ui.expiryDE->minimumDate();
326 if (minDate.isValid() && date < minDate) {
329 const auto maxDate = ui.expiryDE->maximumDate();
330 if (maxDate.isValid() && date > maxDate) {
336 void setExpiryDate(
QDate date)
339 ui.expiryDE->setDate(forceDateIntoAllowedRange(date));
342 if (unlimitedValidityIsAllowed()) {
343 ui.expiryDE->setDate(date);
346 if (ui.expiryCB->isEnabled()) {
347 ui.expiryCB->setChecked(ui.expiryDE->isValid());
352 KeyParameters technicalParameters;
357 , d(new Private{this})
359 resize(std::max(sizeHint().width(), d->ui.expander->contentWidth()) + 20, sizeHint().height() + 20);
362OpenPGPCertificateCreationDialog::~OpenPGPCertificateCreationDialog() =
default;
364void OpenPGPCertificateCreationDialog::setName(
const QString &name)
366 d->ui.nameAndEmail->setName(name);
369QString OpenPGPCertificateCreationDialog::name()
const
371 return d->ui.nameAndEmail->name();
374void OpenPGPCertificateCreationDialog::setEmail(
const QString &email)
376 d->ui.nameAndEmail->setEmail(email);
379QString OpenPGPCertificateCreationDialog::email()
const
381 return d->ui.nameAndEmail->email();
384void Kleo::OpenPGPCertificateCreationDialog::setKeyParameters(
const Kleo::KeyParameters ¶meters)
386 setName(parameters.name());
387 const auto emails = parameters.emails();
388 if (!emails.empty()) {
389 setEmail(emails.front());
391 d->setTechnicalParameters(parameters);
394KeyParameters OpenPGPCertificateCreationDialog::keyParameters()
const
397 auto parameters = d->technicalParameters;
398 if (!name().isEmpty()) {
399 parameters.setName(name());
401 if (!email().isEmpty()) {
402 parameters.setEmail(email());
407void Kleo::OpenPGPCertificateCreationDialog::setProtectKeyWithPassword(
bool protectKey)
409 d->ui.withPassCheckBox->setChecked(protectKey);
412bool OpenPGPCertificateCreationDialog::protectKeyWithPassword()
const
414 return d->ui.withPassCheckBox->isChecked();
417#include "moc_openpgpcertificatecreationdialog.cpp"
void dateChanged(const QDate &date)
Dialog to create a new OpenPGP key.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void errorList(QWidget *parent, const QString &text, const QStringList &strlist, const QString &title=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
void addItem(const QIcon &icon, const QString &text, const QVariant &userData)
void setCurrentIndex(int index)
void currentIndexChanged(int index)
int findData(const QVariant &data, int role, Qt::MatchFlags flags) const const
bool isValid(int year, int month, int day)
void setFrameStyle(int style)
void setBuddy(QWidget *buddy)
void setText(const QString &)
void setWordWrap(bool on)
void setContentsMargins(const QMargins &margins)
void push_back(parameter_type value)
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
QString fromStdString(const std::string &str)