diff options
Diffstat (limited to '')
-rw-r--r-- | include/gpg/GpgContext.h | 14 | ||||
-rw-r--r-- | include/ui/keypair_details/KeyPairUIDTab.h | 15 | ||||
-rw-r--r-- | include/ui/keypair_details/KeySignDialog.h | 44 | ||||
-rw-r--r-- | include/ui/widgets/KeyList.h | 2 | ||||
-rw-r--r-- | src/MainWindow.cpp | 6 | ||||
-rw-r--r-- | src/gpg/GpgContext.cpp | 88 | ||||
-rw-r--r-- | src/gpg/GpgKey.cpp | 7 | ||||
-rwxr-xr-x | src/ui/KeyMgmt.cpp | 10 | ||||
-rwxr-xr-x | src/ui/SettingsDialog.cpp | 5 | ||||
-rw-r--r-- | src/ui/VerifyKeyDetailBox.cpp | 2 | ||||
-rw-r--r-- | src/ui/VerifyNotification.cpp | 2 | ||||
-rw-r--r-- | src/ui/keypair_details/KeyPairDetailTab.cpp | 3 | ||||
-rw-r--r-- | src/ui/keypair_details/KeyPairUIDTab.cpp | 52 | ||||
-rw-r--r-- | src/ui/keypair_details/KeySignDialog.cpp | 64 | ||||
-rw-r--r-- | src/ui/widgets/KeyList.cpp | 11 |
15 files changed, 247 insertions, 78 deletions
diff --git a/include/gpg/GpgContext.h b/include/gpg/GpgContext.h index 92a8200c..5fd54618 100644 --- a/include/gpg/GpgContext.h +++ b/include/gpg/GpgContext.h @@ -104,11 +104,11 @@ namespace GpgME { void exportSecretKey(const QString &uid, QByteArray *outBuffer); - void getKeyDetails(const QString &uid, GpgKey& key); - void getSigners(QVector<GpgKey> &signer); - void signKey(const QVector<GpgKey> &signer, const GpgKey &target, const QString& uid); + void setSigners(const QVector<GpgKey> &keys); + + void signKey(const GpgKey &target, const QString& uid, const QDateTime *expires); gpgme_signature_t verify(QByteArray *inBuffer, QByteArray *sigBuffer = nullptr); @@ -124,7 +124,7 @@ namespace GpgME { GpgKey getKeyByFpr(const QString &fpr); - GpgKey getKeyById(const QString &id); + const GpgKey & getKeyById(const QString &id); static QString gpgErrString(gpgme_error_t err); @@ -146,10 +146,14 @@ namespace GpgME { void signalKeyDBChanged(); + void signalKeyUpdated(const QString &key_id); + private slots: void slotRefreshKeyList(); + void slotUpdateKeyList(const QString &key_id); + private: gpgme_ctx_t mCtx{}; gpgme_data_t in{}; @@ -162,7 +166,7 @@ namespace GpgME { QSettings settings; GpgKeyList mKeyList; - QMap<QString, GpgKey> mKeyMap; + QMap<QString, GpgKey *> mKeyMap; void fetch_keys(); diff --git a/include/ui/keypair_details/KeyPairUIDTab.h b/include/ui/keypair_details/KeyPairUIDTab.h index ae476a1f..6aca3dd8 100644 --- a/include/ui/keypair_details/KeyPairUIDTab.h +++ b/include/ui/keypair_details/KeyPairUIDTab.h @@ -28,12 +28,14 @@ #include "GpgFrontend.h" #include "gpg/GpgContext.h" +#include "KeySignDialog.h" + class KeyPairUIDTab : public QWidget { Q_OBJECT public: - KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey& key, QWidget *parent); + KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget *parent); private: @@ -41,15 +43,15 @@ private: void createSignList(); - GpgME::GpgContext *mCtx; - - const GpgKey &key; + void getUIDChecked(QVector<UID> &uids); - QTableWidget *uidList; + GpgME::GpgContext *mCtx; - QTableWidget *sigList; + const GpgKey &mKey; + QTableWidget *uidList{}; + QTableWidget *sigList{}; private slots: @@ -57,6 +59,7 @@ private slots: void slotRefreshSigList(); + void slotAddSign(); }; diff --git a/include/ui/keypair_details/KeySignDialog.h b/include/ui/keypair_details/KeySignDialog.h new file mode 100644 index 00000000..075459de --- /dev/null +++ b/include/ui/keypair_details/KeySignDialog.h @@ -0,0 +1,44 @@ +// +// Created by eric on 2021/5/24. +// + +#ifndef GPGFRONTEND_KEYSIGNDIALOG_H +#define GPGFRONTEND_KEYSIGNDIALOG_H + +#include "GpgFrontend.h" + +#include "gpg/GpgContext.h" +#include "ui/widgets/KeyList.h" + +class KeySignDialog : public QDialog { + Q_OBJECT + +public: + + explicit KeySignDialog(GpgME::GpgContext *ctx, const GpgKey &key, const QVector<UID> &uid, QWidget *parent = nullptr); + +private: + + GpgME::GpgContext *mCtx; + + KeyList *mKeyList; + + QPushButton *signKeyButton; + + QDateTimeEdit *expiresEdit; + + QCheckBox *nonExpireCheck; + + const QVector<UID> &mUids; + + const GpgKey &mKey; + + +private slots: + + void slotSignKey(); + +}; + + +#endif //GPGFRONTEND_KEYSIGNDIALOG_H diff --git a/include/ui/widgets/KeyList.h b/include/ui/widgets/KeyList.h index 6af54518..c4169f4a 100644 --- a/include/ui/widgets/KeyList.h +++ b/include/ui/widgets/KeyList.h @@ -69,6 +69,8 @@ public: QStringList *getChecked(); + void getCheckedKeys(QVector<GpgKey> &keys); + QStringList *getPrivateChecked(); QStringList *getAllPrivateKeys(); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index cf100a14..f4d2badb 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -855,8 +855,7 @@ void MainWindow::slotCopyMailAddressToClipboard() { if (mKeyList->getSelected()->isEmpty()) { return; } - GpgKey key; - mCtx->getKeyDetails(mKeyList->getSelected()->first(), key); + auto &key = mCtx->getKeyById(mKeyList->getSelected()->first()); QClipboard *cb = QApplication::clipboard(); QString mail = key.email; cb->setText(mail); @@ -866,8 +865,7 @@ void MainWindow::slotShowKeyDetails() { if (mKeyList->getSelected()->isEmpty()) { return; } - GpgKey key; - mCtx->getKeyDetails(mKeyList->getSelected()->first(), key); + auto &key = mCtx->getKeyById(mKeyList->getSelected()->first()); if (key.good) { new KeyDetailsDialog(mCtx, key, this); } diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp index 91602a70..3e1f59c1 100644 --- a/src/gpg/GpgContext.cpp +++ b/src/gpg/GpgContext.cpp @@ -186,7 +186,7 @@ namespace GpgME { const char *userid = userid_utf8.constData(); auto algo_utf8 = (params->getAlgo() + params->getKeySizeStr()).toUtf8(); const char *algo = algo_utf8.constData(); - unsigned long expires = params->getExpired().toTime_t(); + unsigned long expires = QDateTime::currentDateTime().secsTo(params->getExpired()); unsigned int flags = 0; if (!params->isSubKey()) { @@ -253,19 +253,6 @@ namespace GpgME { return true; } - void GpgContext::getKeyDetails(const QString &uid, GpgKey &key) { - gpgme_key_t gpgme_key; - - // try secret - gpgme_get_key(mCtx, uid.toUtf8().constData(), &gpgme_key, 1); - // ok, its a public key - if (!gpgme_key) { - gpgme_get_key(mCtx, uid.toUtf8().constData(), &gpgme_key, 0); - } - - key.parse(gpgme_key); - } - /** * List all availabe Keys (VERY much like kgpgme) */ @@ -297,9 +284,8 @@ namespace GpgME { if (!key->subkeys) continue; - GpgKey gpg_key(key); - - keys_map.insert(gpg_key.id, gpg_key); + keys.append(GpgKey(key)); + keys_map.insert(keys.back().id, &keys.back()); gpgme_key_unref(key); } @@ -343,10 +329,6 @@ namespace GpgME { return; } - for(auto &gpg_key : keys_map) { - keys.append(gpg_key); - } - mKeyList = keys; } @@ -855,6 +837,7 @@ namespace GpgME { } void GpgContext::slotRefreshKeyList() { + qDebug() << "Refreshing Keys"; this->fetch_keys(); } @@ -870,27 +853,41 @@ namespace GpgME { return GpgKey(nullptr); } -/** - * note: is_private_key status is not returned - */ - GpgKey GpgContext::getKeyById(const QString &id) { + /** + * note: is_private_key status is not returned + */ + const GpgKey &GpgContext::getKeyById(const QString &id) { - //GpgKeyList list = this->fetch_keys(); - foreach (GpgKey key, mKeyList) { - if (key.id == id) { - return key; - } - } + auto it = mKeyMap.find(id); - return GpgKey(nullptr); + if(it != mKeyMap.end()) { + return *it.value(); + } + + throw std::runtime_error("key not found"); } QString GpgContext::getGpgmeVersion() { return QString(gpgme_check_version(nullptr)); } - void GpgContext::signKey(const QVector<GpgKey> &signer, const GpgKey &target, const QString &uid) { + void GpgContext::signKey(const GpgKey &target, const QString &uid, const QDateTime *expires) { + + unsigned int flags = 0; + + unsigned int expires_time_t = 0; + if (expires == nullptr) { + flags |= GPGME_KEYSIGN_NOEXPIRE; + } else { + expires_time_t = QDateTime::currentDateTime().secsTo(*expires); + } + + auto gpgmeError = + gpgme_op_keysign(mCtx, target.key_refer, uid.toUtf8().constData(), expires_time_t, flags); + + checkErr(gpgmeError); + emit signalKeyUpdated(target.id); } const GpgKeyList &GpgContext::getKeys() const { @@ -900,17 +897,36 @@ namespace GpgME { void GpgContext::getSigners(QVector<GpgKey> &signer) { auto count = gpgme_signers_count(mCtx); signer.clear(); - for(auto i = 0; i < count; i++){ + for (auto i = 0; i < count; i++) { auto key = gpgme_signers_enum(mCtx, i); auto it = mKeyMap.find(key->subkeys->keyid); - if(it == mKeyMap.end()) { + if (it == mKeyMap.end()) { + qDebug() << "Inconsistent state"; signer.push_back(GpgKey(key)); } else { - signer.push_back(*it); + signer.push_back(*it.value()); } } } + void GpgContext::setSigners(const QVector<GpgKey> &keys) { + gpgme_signers_clear(mCtx); + unsigned int count = 0; + for (const auto &key : keys) { + count = gpgme_signers_add(mCtx, key.key_refer); + } + if (keys.length() != count) { + qDebug() << "Now All Keys Added"; + } + } + + void GpgContext::slotUpdateKeyList(const QString &key_id) { + auto it = mKeyMap.find(key_id); + if (it != mKeyMap.end()) { + it.value()->parse(it.value()->key_refer); + } + } + } diff --git a/src/gpg/GpgKey.cpp b/src/gpg/GpgKey.cpp index 51ab2158..99972eee 100644 --- a/src/gpg/GpgKey.cpp +++ b/src/gpg/GpgKey.cpp @@ -28,6 +28,8 @@ void GpgKey::parse(gpgme_key_t key) { if(key == nullptr) return; + + good = true; key_refer = key; gpgme_key_ref(key_refer); @@ -68,6 +70,7 @@ void GpgKey::parse(gpgme_key_t key) { break; } + uids.clear(); auto uid = key->uids; while (uid != nullptr) { @@ -75,13 +78,13 @@ void GpgKey::parse(gpgme_key_t key) { uid = uid->next; } - if (!uids.isEmpty()) { name = uids.first().name; email = uids.first().email; comment = uids.first().comment; } + subKeys.clear(); auto next = key->subkeys; while (next != nullptr) { @@ -169,6 +172,7 @@ GpgKey &GpgKey::operator=(const GpgKey &k) { good = k.good; subKeys = k.subKeys; + uids = k.uids; key_refer = k.key_refer; gpgme_key_ref(key_refer); @@ -197,6 +201,7 @@ GpgKey::GpgKey(const GpgKey &k) : good = k.good; subKeys = k.subKeys; + uids = k.uids; key_refer = k.key_refer; gpgme_key_ref(key_refer); diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp index b1699483..d40928ee 100755 --- a/src/ui/KeyMgmt.cpp +++ b/src/ui/KeyMgmt.cpp @@ -234,8 +234,7 @@ void KeyMgmt::deleteKeysWithWarning(QStringList *uidList) } QString keynames; for (const auto &uid : *uidList) { - GpgKey key; - mCtx->getKeyDetails(uid, key); + auto &key = mCtx->getKeyById(uid); keynames.append(key.name); keynames.append("<i> <"); keynames.append(key.email); @@ -258,9 +257,7 @@ void KeyMgmt::slotShowKeyDetails() return; } - GpgKey key; - - mCtx->getKeyDetails(mKeyList->getSelected()->first(), key); + auto &key = mCtx->getKeyById(mKeyList->getSelected()->first()); new KeyDetailsDialog(mCtx, key); } @@ -271,8 +268,7 @@ void KeyMgmt::slotExportKeyToFile() if (!mCtx->exportKeys(mKeyList->getChecked(), keyArray)) { return; } - GpgKey key; - mCtx->getKeyDetails(mKeyList->getChecked()->first(), key); + auto &key = mCtx->getKeyById(mKeyList->getSelected()->first()); QString fileString = key.name + " " + key.email+ "(" + key.id+ ")_pub.asc"; QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, tr("Key Files") + " (*.asc *.txt);;All Files (*)"); diff --git a/src/ui/SettingsDialog.cpp b/src/ui/SettingsDialog.cpp index f7cd0c50..2e174b91 100755 --- a/src/ui/SettingsDialog.cpp +++ b/src/ui/SettingsDialog.cpp @@ -184,8 +184,9 @@ GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent) keyIds.insert("", tr("<none>")); foreach (QString keyid, *mKeyList->getAllPrivateKeys()) { - GpgKey key; - mCtx->getKeyDetails(keyid, key); + + auto &key = mCtx->getKeyById(keyid); + QString newKey = " (" + keyid + ")"; if (!QString(key.email).isEmpty()) { newKey.prepend(" <" + key.email + ">"); diff --git a/src/ui/VerifyKeyDetailBox.cpp b/src/ui/VerifyKeyDetailBox.cpp index 57f70a62..4252e10f 100644 --- a/src/ui/VerifyKeyDetailBox.cpp +++ b/src/ui/VerifyKeyDetailBox.cpp @@ -66,7 +66,7 @@ VerifyKeyDetailBox::VerifyKeyDetailBox(QWidget *parent, GpgME::GpgContext *ctx, break; } default: { - GpgKey key = mCtx->getKeyById(signature->fpr); + GpgKey key = mCtx->getKeyByFpr(signature->fpr); if(!key.good) break; diff --git a/src/ui/VerifyNotification.cpp b/src/ui/VerifyNotification.cpp index b5b2c890..9283120f 100644 --- a/src/ui/VerifyNotification.cpp +++ b/src/ui/VerifyNotification.cpp @@ -130,7 +130,7 @@ bool VerifyNotification::slotRefresh() { case GPG_ERR_BAD_SIGNATURE: { textIsSigned = 3; verifyStatus = VERIFY_ERROR_CRITICAL; - GpgKey key = mCtx->getKeyById(sign->fpr); + GpgKey key = mCtx->getKeyByFpr(sign->fpr); if(!key.good) break; diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp index 6974157f..f0819b1f 100644 --- a/src/ui/keypair_details/KeyPairDetailTab.cpp +++ b/src/ui/keypair_details/KeyPairDetailTab.cpp @@ -175,8 +175,7 @@ void KeyPairDetailTab::slotExportPrivateKey() { if (ret == QMessageBox::Ok) { auto *keyArray = new QByteArray(); mCtx->exportSecretKey(*keyid, keyArray); - GpgKey key; - mCtx->getKeyDetails(*keyid, key); + auto &key = mCtx->getKeyById(*keyid); QString fileString = key.name + " " +key.email + "(" + key.id + ")_pub_sec.asc"; QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString, diff --git a/src/ui/keypair_details/KeyPairUIDTab.cpp b/src/ui/keypair_details/KeyPairUIDTab.cpp index 8ca68d60..f9f4d496 100644 --- a/src/ui/keypair_details/KeyPairUIDTab.cpp +++ b/src/ui/keypair_details/KeyPairUIDTab.cpp @@ -4,7 +4,7 @@ #include "ui/keypair_details/KeyPairUIDTab.h" -KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget *parent) : QWidget(parent), key(key) { +KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget *parent) : QWidget(parent), mKey(key) { mCtx = ctx; @@ -39,6 +39,7 @@ KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget connect(mCtx, SIGNAL(signalKeyDBChanged()), this, SLOT(slotRefreshUIDList())); connect(mCtx, SIGNAL(signalKeyDBChanged()), this, SLOT(slotRefreshSigList())); + connect(addSigButton, SIGNAL(clicked(bool)), this, SLOT(slotAddSign())); slotRefreshUIDList(); slotRefreshSigList(); @@ -61,7 +62,7 @@ void KeyPairUIDTab::createUIDList() { uidList->setAlternatingRowColors(true); QStringList labels; - labels << tr("Name") << tr("Email") << tr("Comment"); + labels << tr("Operate") << tr("Name") << tr("Email") << tr("Comment"); uidList->setHorizontalHeaderLabels(labels); uidList->horizontalHeader()->setStretchLastSection(true); } @@ -86,32 +87,36 @@ void KeyPairUIDTab::createSignList() { labels << tr("Type") << tr("Name") << tr("Pubkey Id") << tr("Create Time") << tr("Valid Time"); sigList->setHorizontalHeaderLabels(labels); sigList->horizontalHeader()->setStretchLastSection(true); + } void KeyPairUIDTab::slotRefreshUIDList() { + int row = 0; uidList->clearContents(); - uidList->setRowCount(key.uids.size()); + uidList->setRowCount(mKey.uids.size()); uidList->setSelectionMode(QAbstractItemView::SingleSelection); - for(const auto& uid : key.uids) { + for(const auto& uid : mKey.uids) { auto *tmp0 = new QTableWidgetItem(uid.name); - uidList->setItem(row, 0, tmp0); + uidList->setItem(row, 1, tmp0); auto *tmp1 = new QTableWidgetItem(uid.email); - uidList->setItem(row, 1, tmp1); + uidList->setItem(row, 2, tmp1); auto *tmp2 = new QTableWidgetItem(uid.comment); - uidList->setItem(row, 2, tmp2); + uidList->setItem(row, 3, tmp2); + + auto *tmp3 = new QTableWidgetItem(QString::number(row)); + tmp3->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable); + tmp3->setTextAlignment(Qt::AlignCenter); + tmp3->setCheckState(Qt::Unchecked); + uidList->setItem(row, 0, tmp3); row++; } - - - - } void KeyPairUIDTab::slotRefreshSigList() { @@ -119,13 +124,13 @@ void KeyPairUIDTab::slotRefreshSigList() { sigList->clearContents(); - for(const auto& uid : key.uids) { + for(const auto& uid : mKey.uids) { row += uid.signatures.size(); } sigList->setRowCount(row); row = 0; - for(const auto& uid : key.uids) { + for(const auto& uid : mKey.uids) { // Only Show Selected UID's Signatures if(!uidList->item(row, 0)->isSelected()) @@ -151,3 +156,24 @@ void KeyPairUIDTab::slotRefreshSigList() { } } } + +void KeyPairUIDTab::slotAddSign() { + + QVector<UID> selected_uids; + + getUIDChecked(selected_uids); + + auto keySignDialog = new KeySignDialog(mCtx, mKey, selected_uids, this); + keySignDialog->show(); +} + +void KeyPairUIDTab::getUIDChecked(QVector<UID> &selected_uids) { + + auto &uids = mKey.uids; + + for (int i = 0; i < uidList->rowCount(); i++) { + if (uidList->item(i, 0)->checkState() == Qt::Checked) { + selected_uids.push_back(uids[i]); + } + } +} diff --git a/src/ui/keypair_details/KeySignDialog.cpp b/src/ui/keypair_details/KeySignDialog.cpp new file mode 100644 index 00000000..5a9b9118 --- /dev/null +++ b/src/ui/keypair_details/KeySignDialog.cpp @@ -0,0 +1,64 @@ +// +// Created by eric on 2021/5/24. +// + +#include "ui/keypair_details/KeySignDialog.h" + +KeySignDialog::KeySignDialog(GpgME::GpgContext *ctx, const GpgKey &key, const QVector<UID> &uid, QWidget *parent) : + mCtx(ctx), mUids(uid), QDialog(parent), mKey(key) { + + mKeyList = new KeyList(ctx, + KeyListRow::ONLY_SECRET_KEY, + KeyListColumn::NAME | KeyListColumn::EmailAddress, + this); + + signKeyButton = new QPushButton("Sign"); + + /** + * A DateTime after 5 Years is recommend. + */ + expiresEdit = new QDateTimeEdit(QDateTime::currentDateTime().addYears(5)); + expiresEdit->setMinimumDateTime(QDateTime::currentDateTime()); + + /** + * Note further that the OpenPGP protocol uses 32 bit values for timestamps + * and thus can only encode dates up to the year 2106. + */ + expiresEdit->setMaximumDate(QDate(2106, 1, 1)); + + nonExpireCheck = new QCheckBox("Non Expired"); + nonExpireCheck->setTristate(false); + + connect(nonExpireCheck, &QCheckBox::stateChanged, this, [this] (int state) -> void { + if(state == 0) + expiresEdit->setDisabled(false); + else + expiresEdit->setDisabled(true); + }); + + auto layout = new QGridLayout(); + + auto timeLayout = new QGridLayout(); + + layout->addWidget(mKeyList, 0, 0); + layout->addWidget(signKeyButton, 2, 0, Qt::AlignRight); + timeLayout->addWidget(new QLabel(tr("Expired Time")), 0, 0); + timeLayout->addWidget(expiresEdit, 0, 1); + timeLayout->addWidget(nonExpireCheck, 0, 2); + layout->addLayout(timeLayout, 1, 0); + + this->setLayout(layout); + this->setModal(true); + this->setWindowTitle(tr("Sign For Key's UID")); + this->adjustSize(); +} + +void KeySignDialog::slotSignKey() { + QVector<GpgKey> keys; + mKeyList->getCheckedKeys(keys); + mCtx->setSigners(keys); + const auto expires = expiresEdit->dateTime(); + + for(const auto &uid : mUids) + mCtx->signKey(mKey, uid.uid, &expires); +} diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp index 337c1fc5..2fdec43e 100644 --- a/src/ui/widgets/KeyList.cpp +++ b/src/ui/widgets/KeyList.cpp @@ -385,3 +385,14 @@ void KeyList::uploadFinished() reply->deleteLater(); } + +void KeyList::getCheckedKeys(QVector<GpgKey> &keys) { + + keys.clear(); + + for (int i = 0; i < mKeyList->rowCount(); i++) { + if (mKeyList->item(i, 0)->isSelected() == 1) { + keys.push_back(buffered_keys[i]); + } + } +} |