diff --git a/K7Main.cpp b/K7Main.cpp index 60b5d2a..e0ef1e1 100644 --- a/K7Main.cpp +++ b/K7Main.cpp @@ -32,6 +32,7 @@ K7Main::K7Main(const WEnvironment& env) m_btnImport = NULL; m_btnDelete = NULL; m_btnCreate = NULL; + m_btnExport = NULL; WApplication::setTitle(_APPNAME_); const WString bundle = WApplication::appRoot() + _APPNAME_; WApplication::instance()->messageResourceBundle().use(bundle.toUTF8()); @@ -139,6 +140,11 @@ K7Main::Create() } vblButtons->addSpacing(150); vblButtons->addStretch(1); + // Everyone can export a key + m_btnExport = new WPushButton(TR("Export")); + m_btnExport->setToolTip(TR("TTTExport")); + m_btnExport->hide(); + vblButtons->addWidget(unique_ptr (m_btnExport)); if (m_config->CanCreateKeys()) { m_btnCreate = new WPushButton(TR("Create")); @@ -307,6 +313,8 @@ void K7Main::OnKeyAnchorClicked(WAnchor * source) DisplaySubKeys(id, secret); if (m_config->CanDelete()) // m_btnDelete is NULL otherwise m_btnDelete->setHidden(!m_keyringIO->CanKeyBeDeleted(id)); + + m_keyringIO->PrepareExport(id, secret); } void K7Main::DisplayUids(const WString& fullKeyID, bool secret) diff --git a/K7Main.h b/K7Main.h index a75c765..327d920 100644 --- a/K7Main.h +++ b/K7Main.h @@ -56,6 +56,7 @@ private: WPushButton * m_btnImport; WPushButton * m_btnDelete; WPushButton * m_btnCreate; + WPushButton * m_btnExport; WTreeTable * m_ttbKeys; WTreeTable * m_ttbUids; WTreeTable * m_ttbSubKeys; diff --git a/KeyringIO.cpp b/KeyringIO.cpp index 79680f9..3d2375c 100644 --- a/KeyringIO.cpp +++ b/KeyringIO.cpp @@ -11,6 +11,10 @@ #include "GpgMEWorker.h" #include "GpgMECWorker.h" #include "Tools.h" +#include +#include + +using namespace std; KeyringIO::KeyringIO(K7Main * owner) { @@ -24,6 +28,7 @@ KeyringIO::KeyringIO(K7Main * owner) m_btnImport = m_owner->m_btnImport; m_btnDelete = m_owner->m_btnDelete; m_btnCreate = m_owner->m_btnCreate; + m_btnExport = m_owner->m_btnExport; m_leSearch = m_owner->m_leSearch; if (m_config->CanImport()) @@ -244,3 +249,73 @@ void KeyringIO::DoCreateKey() m_owner->Search(); } } + +void KeyringIO::PrepareExport(const WString& fpr, bool isSecret) +{ + WLink link; + shared_ptr shResource = + make_shared + (fpr, isSecret, "appliation/pgp-keys", m_tmwMessage); + link.setResource(shResource); + m_btnExport->setLink(link); + if (isSecret) + m_btnExport->hide(); + else + m_btnExport->show(); +} + +ExportKeyStreamResource::ExportKeyStreamResource(const WString& fpr, + bool isSecret, + TransientMessageWidget * tmw) +: WStreamResource() +{ + m_fpr = fpr; + m_isSecret = isSecret; + m_tmwMessage = tmw; +} + +ExportKeyStreamResource::ExportKeyStreamResource(const WString& fpr, + bool isSecret, + const string& mimeType, + TransientMessageWidget * tmw) +: WStreamResource(mimeType) +{ + m_fpr = fpr; + m_isSecret = isSecret; + m_tmwMessage = tmw; +} + +ExportKeyStreamResource::~ExportKeyStreamResource() +{ + beingDeleted(); +} + +void ExportKeyStreamResource::handleRequest(const Http::Request& request, + Http::Response& response) +{ + /* + * Private keys cannot be exported with loopback pinentry. + * Let's hope it gets better someday. + */ + if (m_isSecret) + { + m_tmwMessage->SetText(TR("TTTExport")); + return; + } + string buffer; + if (!request.continuation()) // Needed for WStreamResource ? + { + Error e; + GpgMEWorker gpgw; + e = gpgw.ExportPublicKey(m_fpr.toUTF8().c_str(), buffer); + if (e.code() != 0) + { + m_tmwMessage->SetText(e.asString()); + return; + } + suggestFileName(m_fpr + WString(".asc"), ContentDisposition::Attachment); + } + + istrstream bufStream(buffer.c_str()); + handleRequestPiecewise(request, response, bufStream); +} diff --git a/KeyringIO.h b/KeyringIO.h index 887a891..a5df57f 100644 --- a/KeyringIO.h +++ b/KeyringIO.h @@ -12,6 +12,7 @@ #include "K7Main.h" #include +#include #include "PopupUploader.h" #include "PopupDeleter.h" #include "PopupCreate.h" @@ -35,22 +36,23 @@ public: private: KeyringIO(K7Main * owner); virtual ~KeyringIO(); - + K7Main * m_owner; PopupUpload * m_popupUpload; PopupDelete * m_popupDelete; PopupCreate * m_popupCreate; - + // Variables from m_owner mapped here. AppConfig * m_config; TransientMessageWidget * m_tmwMessage; WPushButton * m_btnUpload; WPushButton * m_btnImport; WPushButton * m_btnDelete; - WPushButton * m_btnCreate ; + WPushButton * m_btnCreate; + WPushButton * m_btnExport; WLineEdit * m_leSearch; - + /** * Shows a non-blocking popup to upload a key, * with forward confirmation for upload. @@ -90,6 +92,37 @@ private: */ void OnUploadCompleted(const WString& spool); + void PrepareExport(const WString& fpr, bool isSecret); +}; + +/** + * Export a public key for download. + * \n Secret keys cannot be exported and are excluded. + * @param fpr + * @param isSecret + * @param tmw + */ +class ExportKeyStreamResource : public WStreamResource +{ +public: + ExportKeyStreamResource(const WString& fpr, bool isSecret, + TransientMessageWidget * tmw); + ExportKeyStreamResource(const WString& fpr, bool isSecret, + const string& mimeType, + TransientMessageWidget * tmw); + virtual ~ExportKeyStreamResource(); + /** + * Actually exports the public key and starts download on success. + * @param request + * @param response + */ + void handleRequest(const Http::Request& request, + Http::Response& response) override; + +private: + WString m_fpr; + bool m_isSecret; + TransientMessageWidget * m_tmwMessage; }; #endif /* KEYRINGIO_H */ diff --git a/README.md b/README.md index 31b96f2..8d40b9b 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,11 @@ It is developed in C++ as a NetBeans project on the [WebToolkit](https://www.webtoolkit.eu/)(Wt) libraries. -It allows to view, import, create, delete and certify keys. Certification trust level and secret key expiry date can also be changed. -Exporting keys and adding user identities are not (yet) implemented. +It allows to view, import, export, create, delete keys. Certification trust level, secret key expiry date can also be changed, and user identities can be certified. +Export concerns public keys only; secret keys cannot be technically exported on a web server. +Adding user identities is not (yet) implemented. -These keys can then be used by other Wt applications, or web applications based on other libraries, to encrypt and sign data. As such, it suits my personal needs. +Available keys can then be used by other Wt applications, or web applications based on other libraries, to encrypt and sign data. As such, it suits my personal needs. K7 is released under the GPL version 2 license. It does not intend nor need to be a full blown key manager. diff --git a/WTAPPROOT/K7/K7.xml b/WTAPPROOT/K7/K7.xml index d6f53bd..a71232c 100644 --- a/WTAPPROOT/K7/K7.xml +++ b/WTAPPROOT/K7/K7.xml @@ -13,7 +13,7 @@ Upload a new key Add a new key Delete selected key - Create a pair of keys + Create a pair of keys - It is not possible to export secret keys. Consider importing a secret key rather. Sign selected key with your secret key if available Can't upload @@ -129,4 +129,7 @@ Passphrase missing Passphrase does not match Create success : + + Export + Exporting secret keys is technically impossible \ No newline at end of file diff --git a/WTAPPROOT/K7/K7_fr.xml b/WTAPPROOT/K7/K7_fr.xml index b01c13b..6eaa41f 100644 --- a/WTAPPROOT/K7/K7_fr.xml +++ b/WTAPPROOT/K7/K7_fr.xml @@ -13,7 +13,7 @@ Télécharger une nouvelle clé Ajouter une nouvelle clé au porte clés Supprimer la clé sélectionnée - Créer une paire de clés + Créer une paire de clés - Il est impossible d'exporter une clé secrète. Considérez importer une clé secrète plutôt. Signer la clé sélectionnée avec votre clé secrète si elle est disponible Ne peut télécharger @@ -129,4 +129,7 @@ Phrase de passe manquante Les phrases de passe ne sont pas identiques Création réussie : + + Exporter + L'export des clés secrètes est techniquement impossible