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 <kdatecombobox.h>
25#include <KConfigGroup>
26#include <KDateComboBox>
27#include <KLocalizedString>
30#include <KSharedConfig>
33#include <QDialogButtonBox>
38#include <QGpgME/CryptoConfig>
39#include <QGpgME/Protocol>
41#include "libkleo_debug.h"
45static bool unlimitedValidityIsAllowed()
47 return !Kleo::Expiration::maximumExpirationDate().
isValid();
50class OpenPGPCertificateCreationDialog::Private
52 friend class ::Kleo::OpenPGPCertificateCreationDialog;
65 AnimatedExpander *expander;
71 infoLabel =
new QLabel{dialog};
73 mainLayout->addWidget(infoLabel);
84 scrollAreaLayout->setContentsMargins(0, 0, 0, 0);
88 scrollAreaLayout->addWidget(nameAndEmail);
90 withPassCheckBox =
new QCheckBox{
i18n(
"Protect the generated key with a passphrase."), dialog};
92 i18n(
"Encrypts the secret key with an unrecoverable passphrase. You will be asked for the passphrase during key generation."));
93 scrollAreaLayout->addWidget(withPassCheckBox);
95 expander =
new AnimatedExpander(
i18n(
"Advanced options"), {}, dialog);
96 scrollAreaLayout->addWidget(expander);
99 expander->setContentLayout(advancedLayout);
101 keyAlgoLabel =
new QLabel(dialog);
102 keyAlgoLabel->
setText(
i18nc(
"The algorithm and strength of encryption key",
"Key Material"));
106 advancedLayout->addWidget(keyAlgoLabel);
110 advancedLayout->addWidget(keyAlgoCB);
115 expiryCB =
new QCheckBox{
i18nc(
"@option:check",
"Valid until:"), dialog};
116 hbox->addWidget(expiryCB);
119 hbox->addWidget(expiryDE, 1);
121 advancedLayout->addLayout(hbox);
124 scrollAreaLayout->addStretch(1);
126 mainLayout->addWidget(scrollArea);
132 mainLayout->addWidget(buttonBox);
140 , technicalParameters{KeyParameters::OpenPGP}
144 OpenPGPCertificateCreationConfig settings;
145 const auto requiredFields = settings.requiredFields();
149 ui.infoLabel->
setText(nameIsRequired || emailIsRequired
150 ?
i18n(
"Enter a name and an email address to use for the certificate.")
151 :
i18n(
"Enter a name and/or an email address to use for the certificate."));
153 ui.nameAndEmail->setNameIsRequired(nameIsRequired);
154 ui.nameAndEmail->setNameLabel(settings.nameLabel());
155 const auto nameHint = settings.nameHint();
156 ui.nameAndEmail->setNameHint(nameHint.isEmpty() ? settings.namePlaceholder() : nameHint);
157 ui.nameAndEmail->setNamePattern(settings.nameRegex());
158 ui.nameAndEmail->setEmailIsRequired(emailIsRequired);
159 ui.nameAndEmail->setEmailLabel(settings.emailLabel());
160 const auto emailHint = settings.emailHint();
161 ui.nameAndEmail->setEmailHint(emailHint.isEmpty() ? settings.emailPlaceholder() : emailHint);
162 ui.nameAndEmail->setEmailPattern(settings.emailRegex());
164 ui.expander->setVisible(!settings.hideAdvanced());
166 const auto conf = QGpgME::cryptoConfig();
167 const auto entry = getCryptoConfigEntry(conf,
"gpg-agent",
"enforce-passphrase-constraints");
168 if (entry && entry->boolValue()) {
169 qCDebug(LIBKLEO_LOG) <<
"Disabling passphrase check box because of agent config.";
173 ui.withPassCheckBox->
setChecked(settings.withPassphrase());
174 ui.withPassCheckBox->
setEnabled(!settings.isWithPassphraseImmutable());
182 for (
const auto &algorithm : DeVSCompliance::isActive() ? DeVSCompliance::compliantAlgorithms() : availableAlgorithms()) {
185 auto cryptoConfig = QGpgME::cryptoConfig();
187 auto pubkeyEntry = getCryptoConfigEntry(QGpgME::cryptoConfig(),
"gpg",
"default_pubkey_algo");
189 auto algo = pubkeyEntry->stringValue().split(
QLatin1Char(
'/'))[0];
190 if (algo == QStringLiteral(
"ed25519")) {
191 algo = QStringLiteral(
"curve25519");
192 }
else if (algo == QStringLiteral(
"ed448")) {
193 algo = QStringLiteral(
"curve448");
195 auto index = ui.keyAlgoCB->
findData(algo);
208 Kleo::Expiration::setUpExpirationDateComboBox(ui.expiryDE);
210 setExpiryDate(defaultExpirationDate(Kleo::Expiration::ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
211 if (unlimitedValidityIsAllowed()) {
217 ui.expiryDE->setEnabled(checked);
218 if (checked && !ui.expiryDE->isValid()) {
219 setExpiryDate(defaultExpirationDate(Kleo::Expiration::ExpirationOnUnlimitedValidity::InternalDefaultExpiration));
221 updateTechnicalParameters();
224 updateTechnicalParameters();
227 updateTechnicalParameters();
229 updateTechnicalParameters();
230 connect(ui.expander, &AnimatedExpander::startExpanding, q, [
this]() {
231 q->resize(q->sizeHint().width() + 20, q->sizeHint().height() + ui.expander->contentHeight() + 20);
236 void updateTechnicalParameters()
238 technicalParameters = KeyParameters{KeyParameters::OpenPGP};
239 auto keyType = GpgME::Subkey::AlgoUnknown;
240 auto subkeyType = GpgME::Subkey::AlgoUnknown;
241 auto algoString = ui.keyAlgoCB->currentData().toString();
242 if (algoString.startsWith(QStringLiteral(
"rsa"))) {
243 keyType = GpgME::Subkey::AlgoRSA;
244 subkeyType = GpgME::Subkey::AlgoRSA;
245 const auto strength = algoString.mid(3).toInt();
246 technicalParameters.setKeyLength(strength);
247 technicalParameters.setSubkeyLength(strength);
248 }
else if (algoString == QStringLiteral(
"curve25519") || algoString == QStringLiteral(
"curve448")) {
249 keyType = GpgME::Subkey::AlgoEDDSA;
250 subkeyType = GpgME::Subkey::AlgoECDH;
251 if (algoString.endsWith(QStringLiteral(
"25519"))) {
252 technicalParameters.setKeyCurve(QStringLiteral(
"ed25519"));
253 technicalParameters.setSubkeyCurve(QStringLiteral(
"cv25519"));
255 technicalParameters.setKeyCurve(QStringLiteral(
"ed448"));
256 technicalParameters.setSubkeyCurve(QStringLiteral(
"cv448"));
259 keyType = GpgME::Subkey::AlgoECDSA;
260 subkeyType = GpgME::Subkey::AlgoECDH;
261 technicalParameters.setKeyCurve(algoString);
262 technicalParameters.setSubkeyCurve(algoString);
264 technicalParameters.setKeyType(keyType);
265 technicalParameters.setSubkeyType(subkeyType);
267 technicalParameters.setKeyUsage(KeyUsage(KeyUsage::Certify | KeyUsage::Sign));
268 technicalParameters.setSubkeyUsage(KeyUsage(KeyUsage::Encrypt));
270 technicalParameters.setExpirationDate(expiryDate());
274 QDate expiryDate()
const
276 return ui.expiryCB->isChecked() ? ui.expiryDE->date() :
QDate{};
279 void setTechnicalParameters(
const KeyParameters ¶meters)
282 if (parameters.keyType() == GpgME::Subkey::AlgoRSA_S) {
283 index = ui.keyAlgoCB->findData(QStringLiteral(
"rsa%1").arg(parameters.keyLength()));
285 index = ui.keyAlgoCB->findData(parameters.keyCurve());
287 ui.keyAlgoCB->setCurrentIndex(index);
288 setExpiryDate(parameters.expirationDate());
294 if (ui.nameAndEmail->userID().isEmpty() && !ui.nameAndEmail->nameIsRequired() && !ui.nameAndEmail->emailIsRequired()) {
297 const auto nameError = ui.nameAndEmail->nameError();
298 if (!nameError.isEmpty()) {
301 const auto emailError = ui.nameAndEmail->emailError();
302 if (!emailError.isEmpty()) {
305 if (errors.
size() > 1) {
307 }
else if (!errors.
empty()) {
314 QDate forceDateIntoAllowedRange(
QDate date)
const
316 const auto minDate = ui.expiryDE->minimumDate();
317 if (minDate.isValid() && date < minDate) {
320 const auto maxDate = ui.expiryDE->maximumDate();
321 if (maxDate.isValid() && date > maxDate) {
327 void setExpiryDate(
QDate date)
330 ui.expiryDE->
setDate(forceDateIntoAllowedRange(date));
333 if (unlimitedValidityIsAllowed()) {
334 ui.expiryDE->setDate(date);
337 if (ui.expiryCB->isEnabled()) {
338 ui.expiryCB->setChecked(ui.expiryDE->isValid());
343 KeyParameters technicalParameters;
348 , d(new Private{this})
350 resize(sizeHint().width() + 20, sizeHint().height() + 20);
353OpenPGPCertificateCreationDialog::~OpenPGPCertificateCreationDialog() =
default;
355void OpenPGPCertificateCreationDialog::setName(
const QString &name)
357 d->ui.nameAndEmail->setName(name);
360QString OpenPGPCertificateCreationDialog::name()
const
362 return d->ui.nameAndEmail->name();
365void OpenPGPCertificateCreationDialog::setEmail(
const QString &email)
367 d->ui.nameAndEmail->setEmail(email);
370QString OpenPGPCertificateCreationDialog::email()
const
372 return d->ui.nameAndEmail->email();
375void Kleo::OpenPGPCertificateCreationDialog::setKeyParameters(
const Kleo::KeyParameters ¶meters)
377 setName(parameters.name());
378 const auto emails = parameters.emails();
379 if (!emails.empty()) {
380 setEmail(emails.front());
382 d->setTechnicalParameters(parameters);
385KeyParameters OpenPGPCertificateCreationDialog::keyParameters()
const
388 auto parameters = d->technicalParameters;
389 if (!name().isEmpty()) {
390 parameters.setName(name());
392 if (!email().isEmpty()) {
393 parameters.setEmail(email());
398void Kleo::OpenPGPCertificateCreationDialog::setProtectKeyWithPassword(
bool protectKey)
400 d->ui.withPassCheckBox->setChecked(protectKey);
403bool OpenPGPCertificateCreationDialog::protectKeyWithPassword()
const
405 return d->ui.withPassCheckBox->isChecked();
408#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)
bool setDate(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)