Allow exporting public keys.

Secret keys cannot be exported because the loopback pinentry mechanism
fails to work.
This commit is contained in:
SET
2020-11-15 19:32:08 +01:00
parent 9ae83ed7bd
commit e312ac1efd
7 changed files with 133 additions and 9 deletions

View File

@@ -32,6 +32,7 @@ K7Main::K7Main(const WEnvironment& env)
m_btnImport = NULL; m_btnImport = NULL;
m_btnDelete = NULL; m_btnDelete = NULL;
m_btnCreate = NULL; m_btnCreate = NULL;
m_btnExport = NULL;
WApplication::setTitle(_APPNAME_); WApplication::setTitle(_APPNAME_);
const WString bundle = WApplication::appRoot() + _APPNAME_; const WString bundle = WApplication::appRoot() + _APPNAME_;
WApplication::instance()->messageResourceBundle().use(bundle.toUTF8()); WApplication::instance()->messageResourceBundle().use(bundle.toUTF8());
@@ -139,6 +140,11 @@ K7Main::Create()
} }
vblButtons->addSpacing(150); vblButtons->addSpacing(150);
vblButtons->addStretch(1); 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<WPushButton> (m_btnExport));
if (m_config->CanCreateKeys()) if (m_config->CanCreateKeys())
{ {
m_btnCreate = new WPushButton(TR("Create")); m_btnCreate = new WPushButton(TR("Create"));
@@ -307,6 +313,8 @@ void K7Main::OnKeyAnchorClicked(WAnchor * source)
DisplaySubKeys(id, secret); DisplaySubKeys(id, secret);
if (m_config->CanDelete()) // m_btnDelete is NULL otherwise if (m_config->CanDelete()) // m_btnDelete is NULL otherwise
m_btnDelete->setHidden(!m_keyringIO->CanKeyBeDeleted(id)); m_btnDelete->setHidden(!m_keyringIO->CanKeyBeDeleted(id));
m_keyringIO->PrepareExport(id, secret);
} }
void K7Main::DisplayUids(const WString& fullKeyID, bool secret) void K7Main::DisplayUids(const WString& fullKeyID, bool secret)

View File

@@ -56,6 +56,7 @@ private:
WPushButton * m_btnImport; WPushButton * m_btnImport;
WPushButton * m_btnDelete; WPushButton * m_btnDelete;
WPushButton * m_btnCreate; WPushButton * m_btnCreate;
WPushButton * m_btnExport;
WTreeTable * m_ttbKeys; WTreeTable * m_ttbKeys;
WTreeTable * m_ttbUids; WTreeTable * m_ttbUids;
WTreeTable * m_ttbSubKeys; WTreeTable * m_ttbSubKeys;

View File

@@ -11,6 +11,10 @@
#include "GpgMEWorker.h" #include "GpgMEWorker.h"
#include "GpgMECWorker.h" #include "GpgMECWorker.h"
#include "Tools.h" #include "Tools.h"
#include <Wt/WLink.h>
#include <strstream>
using namespace std;
KeyringIO::KeyringIO(K7Main * owner) KeyringIO::KeyringIO(K7Main * owner)
{ {
@@ -24,6 +28,7 @@ KeyringIO::KeyringIO(K7Main * owner)
m_btnImport = m_owner->m_btnImport; m_btnImport = m_owner->m_btnImport;
m_btnDelete = m_owner->m_btnDelete; m_btnDelete = m_owner->m_btnDelete;
m_btnCreate = m_owner->m_btnCreate; m_btnCreate = m_owner->m_btnCreate;
m_btnExport = m_owner->m_btnExport;
m_leSearch = m_owner->m_leSearch; m_leSearch = m_owner->m_leSearch;
if (m_config->CanImport()) if (m_config->CanImport())
@@ -244,3 +249,73 @@ void KeyringIO::DoCreateKey()
m_owner->Search(); m_owner->Search();
} }
} }
void KeyringIO::PrepareExport(const WString& fpr, bool isSecret)
{
WLink link;
shared_ptr<ExportKeyStreamResource> shResource =
make_shared<ExportKeyStreamResource>
(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);
}

View File

@@ -12,6 +12,7 @@
#include "K7Main.h" #include "K7Main.h"
#include <Wt/WComboBox.h> #include <Wt/WComboBox.h>
#include <Wt/WStreamResource.h>
#include "PopupUploader.h" #include "PopupUploader.h"
#include "PopupDeleter.h" #include "PopupDeleter.h"
#include "PopupCreate.h" #include "PopupCreate.h"
@@ -47,7 +48,8 @@ private:
WPushButton * m_btnUpload; WPushButton * m_btnUpload;
WPushButton * m_btnImport; WPushButton * m_btnImport;
WPushButton * m_btnDelete; WPushButton * m_btnDelete;
WPushButton * m_btnCreate ; WPushButton * m_btnCreate;
WPushButton * m_btnExport;
WLineEdit * m_leSearch; WLineEdit * m_leSearch;
@@ -90,6 +92,37 @@ private:
*/ */
void OnUploadCompleted(const WString& spool); 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 */ #endif /* KEYRINGIO_H */

View File

@@ -2,10 +2,11 @@
It is developed in C++ as a NetBeans project on the [WebToolkit](https://www.webtoolkit.eu/)(Wt) libraries. 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. 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.
Exporting keys and adding user identities are not (yet) implemented. 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. K7 is released under the GPL version 2 license. It does not intend nor need to be a full blown key manager.

View File

@@ -13,7 +13,7 @@
<message id='TTTUpload'>Upload a new key</message> <message id='TTTUpload'>Upload a new key</message>
<message id='TTTImport'>Add a new key</message> <message id='TTTImport'>Add a new key</message>
<message id='TTTDelete'>Delete selected key</message> <message id='TTTDelete'>Delete selected key</message>
<message id='TTTCreate'>Create a pair of keys</message> <message id='TTTCreate'>Create a pair of keys - It is not possible to export secret keys. Consider importing a secret key rather.</message>
<message id='TTTSignKey'>Sign selected key with your secret key if available</message> <message id='TTTSignKey'>Sign selected key with your secret key if available</message>
<message id='CantUpload'>Can't upload</message> <message id='CantUpload'>Can't upload</message>
@@ -129,4 +129,7 @@
<message id='ValidatePassphraseMissing'>Passphrase missing</message> <message id='ValidatePassphraseMissing'>Passphrase missing</message>
<message id='ValidatePassphraseNoMatch'>Passphrase does not match</message> <message id='ValidatePassphraseNoMatch'>Passphrase does not match</message>
<message id='CreateSuccess'>Create success : </message> <message id='CreateSuccess'>Create success : </message>
<message id='Export'>Export</message>
<message id='TTTExport'>Exporting secret keys is technically impossible</message>
</messages> </messages>

View File

@@ -13,7 +13,7 @@
<message id='TTTUpload'>Télécharger une nouvelle clé</message> <message id='TTTUpload'>Télécharger une nouvelle clé</message>
<message id='TTTImport'>Ajouter une nouvelle clé au porte clés</message> <message id='TTTImport'>Ajouter une nouvelle clé au porte clés</message>
<message id='TTTDelete'>Supprimer la clé sélectionnée</message> <message id='TTTDelete'>Supprimer la clé sélectionnée</message>
<message id='TTTCreate'>Créer une paire de clés</message> <message id='TTTCreate'>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.</message>
<message id='TTTSignKey'>Signer la clé sélectionnée avec votre clé secrète si elle est disponible</message> <message id='TTTSignKey'>Signer la clé sélectionnée avec votre clé secrète si elle est disponible</message>
<message id='CantUpload'>Ne peut télécharger</message> <message id='CantUpload'>Ne peut télécharger</message>
@@ -129,4 +129,7 @@
<message id='ValidatePassphraseMissing'>Phrase de passe manquante</message> <message id='ValidatePassphraseMissing'>Phrase de passe manquante</message>
<message id='ValidatePassphraseNoMatch'>Les phrases de passe ne sont pas identiques</message> <message id='ValidatePassphraseNoMatch'>Les phrases de passe ne sont pas identiques</message>
<message id='CreateSuccess'>Création réussie : </message> <message id='CreateSuccess'>Création réussie : </message>
<message id='Export'>Exporter</message>
<message id='TTTExport'>L'export des clés secrètes est techniquement impossible</message>
</messages> </messages>