kgpg: implement encryption

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2022-03-14 15:56:34 +02:00
parent f60ec6a68d
commit 61b63feb67
2 changed files with 194 additions and 102 deletions

View file

@ -28,6 +28,7 @@
KGPG::KGPG(QWidget *parent) KGPG::KGPG(QWidget *parent)
: KMainWindow(parent), : KMainWindow(parent),
m_mode(KGPG::EncryptMode),
m_release(false) m_release(false)
{ {
m_ui.setupUi(this); m_ui.setupUi(this);
@ -35,57 +36,95 @@ KGPG::KGPG(QWidget *parent)
// required by context // required by context
kDebug() << gpgme_check_version(NULL); kDebug() << gpgme_check_version(NULL);
#ifndef kgpg_key_query
gpgme_error_t gpgresult = gpgme_new(&m_gpgctx); gpgme_error_t gpgresult = gpgme_new(&m_gpgctx);
if (gpgresult != 0) { if (gpgresult != 0) {
setError(gpgme_strerror(gpgresult)); setError(gpgme_strerror(gpgresult));
return; return;
} }
m_release = true; m_release = true;
}
gpgresult = gpgme_set_keylist_mode(m_gpgctx, GPGME_KEYLIST_MODE_LOCAL); KGPG::~KGPG()
if (gpgresult != 0) { {
setError(gpgme_strerror(gpgresult)); // will crash if not initialized
if (m_release) {
gpgme_release(m_gpgctx);
}
}
void KGPG::setMode(const KGPGMode mode)
{
m_mode = mode;
switch (mode) {
case KGPG::EncryptMode: {
updateKeys(GPGME_KEYLIST_MODE_LOCAL, true);
break;
}
case KGPG::DecryptMode: {
updateKeys(GPGME_KEYLIST_MODE_LOCAL, false);
break;
}
case KGPG::SignMode: {
updateKeys(GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS, true);
break;
}
case KGPG::VerifyMode: {
updateKeys(GPGME_KEYLIST_MODE_LOCAL, false);
break;
}
default: {
Q_ASSERT(false);
break;
}
}
}
void KGPG::setSource(const QString &source)
{
const KUrl sourceurl(source);
m_ui.sourcerequester->setUrl(sourceurl);
m_ui.destinationrequester->setUrl(sourceurl.directory());
}
void KGPG::setError(const char* const error)
{
setError(QString::fromLocal8Bit(error));
}
void KGPG::setError(const QString &error)
{
kWarning() << error;
const QString errormessage = i18n("Error: %1", error);
m_ui.statusbar->showMessage(errormessage);
m_ui.progressbar->setMinimum(0);
m_ui.progressbar->setMaximum(100);
}
void KGPG::start()
{
m_ui.progressbar->setMinimum(0);
m_ui.progressbar->setMaximum(0);
switch (m_mode) {
case KGPG::EncryptMode: {
if (m_keys.isEmpty()) {
setError("No key available");
return; return;
} }
// required by key query const QByteArray kgpgkeyfpr = m_keys.at(m_ui.keysbox->currentIndex()).fpr;
gpgresult = gpgme_op_keylist_start(m_gpgctx, NULL, false); const QByteArray gpginputfile = m_ui.sourcerequester->url().toLocalFile().toLocal8Bit();
if (gpgresult != 0) {
setError(gpgme_strerror(gpgresult));
return;
}
char* gpgkeyfpr = NULL; // will either use key or password from input for encryption
gpgme_key_t gpgkey;
gpgresult = gpgme_op_keylist_next(m_gpgctx, &gpgkey);
while (gpgresult == 0) {
gpgme_user_id_t gpguid = NULL;
for (gpguid = gpgkey->uids; gpguid; gpguid = gpguid->next) {
kWarning() << gpguid->email << gpguid->name << gpguid->comment << gpguid->uidhash << gpgkey->fpr;
::free(gpgkeyfpr);
gpgkeyfpr = ::strdup(gpgkey->fpr);
}
gpgme_key_unref(gpgkey);
gpgresult = gpgme_op_keylist_next(m_gpgctx, &gpgkey);
}
#endif // kgpg_key_query
#ifndef kgpg_encrypt
gpgme_data_t gpgindata; gpgme_data_t gpgindata;
gpgresult = gpgme_data_new_from_file(&gpgindata, "/home/smil3y/gpgme/tests/run-encrypt.c", 1); gpgme_error_t gpgresult = gpgme_data_new_from_file(&gpgindata, gpginputfile.constData(), 1);
if (gpgresult != 0) { if (gpgresult != 0) {
setError(gpgme_strerror(gpgresult)); setError(gpgme_strerror(gpgresult));
::free(gpgkeyfpr);
return; return;
} }
gpgme_key_t gpgencryptkey; gpgme_key_t gpgencryptkey;
gpgresult = gpgme_get_key(m_gpgctx, gpgkeyfpr, &gpgencryptkey, 1); gpgresult = gpgme_get_key(m_gpgctx, kgpgkeyfpr.constData(), &gpgencryptkey, 1);
::free(gpgkeyfpr);
if (gpgresult != 0) { if (gpgresult != 0) {
kWarning() << "gpgme_get_key" << gpgme_strerror(gpgresult); setError(gpgme_strerror(gpgresult));
gpgme_data_release(gpgindata); gpgme_data_release(gpgindata);
return; return;
} }
@ -106,9 +145,32 @@ KGPG::KGPG(QWidget *parent)
gpgme_data_release(gpgoutdata); gpgme_data_release(gpgoutdata);
return; return;
} }
#endif // kgpg_encrypt
#ifndef kgpg_decrypt size_t gpgbuffersize = 0;
char* gpgbuffer = gpgme_data_release_and_get_mem(gpgoutdata, &gpgbuffersize);
const QString outputfile = m_ui.destinationrequester->url().toLocalFile()
+ QDir::separator() + m_ui.sourcerequester->url().fileName() + QLatin1String(".gpg");
QFile encryptedfile(outputfile);
if (!encryptedfile.open(QFile::WriteOnly)) {
setError(encryptedfile.errorString());
gpgme_free(gpgbuffer);
gpgme_data_release(gpgindata);
}
if (encryptedfile.write(gpgbuffer, gpgbuffersize) != gpgbuffersize) {
setError(encryptedfile.errorString());
gpgme_free(gpgbuffer);
gpgme_data_release(gpgindata);
}
// qDebug() << Q_FUNC_INFO << "encrypted" << gpgbuffer;
gpgme_free(gpgbuffer);
gpgme_data_release(gpgindata);
break;
}
case KGPG::DecryptMode: {
#ifdef kgpg_decrypt
gpgme_data_t gpgdecryptoutdata; gpgme_data_t gpgdecryptoutdata;
gpgme_data_new(&gpgdecryptoutdata); gpgme_data_new(&gpgdecryptoutdata);
if (gpgresult != 0) { if (gpgresult != 0) {
@ -131,59 +193,81 @@ KGPG::KGPG(QWidget *parent)
size_t gpgbuffersize = 0; size_t gpgbuffersize = 0;
char* gpgbuffer = gpgme_data_release_and_get_mem(gpgdecryptoutdata, &gpgbuffersize); char* gpgbuffer = gpgme_data_release_and_get_mem(gpgdecryptoutdata, &gpgbuffersize);
kWarning() << "decryption" << gpgbuffer; kWarning() << "decryption" << gpgbuffer;
#endif // kgpg_decrypt
gpgme_free(gpgbuffer); gpgme_free(gpgbuffer);
gpgme_data_release(gpgindata); gpgme_data_release(gpgindata);
gpgme_data_release(gpgoutdata); gpgme_data_release(gpgoutdata);
#endif // kgpg_decrypt
setError("Not implemented");
break;
}
case KGPG::SignMode: {
if (m_keys.isEmpty()) {
setError("No key available");
return;
} }
KGPG::~KGPG() setError("Not implemented");
{ break;
// will crash if not initialized
if (m_release) {
gpgme_release(m_gpgctx);
} }
case KGPG::VerifyMode: {
setError("Not implemented");
break;
} }
void KGPG::setMode(const KGPGMode mode)
{
m_mode = mode;
switch (mode) {
// TODO: implement
default: { default: {
Q_ASSERT(false);
break; break;
} }
} }
} }
void KGPG::setSource(const QString &source) void KGPG::updateKeys(const gpgme_keylist_mode_t gpgmode, const bool secret)
{ {
const KUrl sourceurl(source); m_keys.clear();
m_ui.sourcerequester->setUrl(sourceurl); m_ui.keysbox->clear();
m_ui.destinationrequester->setUrl(sourceurl.directory());
gpgme_error_t gpgresult = gpgme_set_keylist_mode(m_gpgctx, gpgmode);
if (gpgresult != 0) {
setError(gpgme_strerror(gpgresult));
return;
} }
void KGPG::setError(const char* const error) // required by key query
{ gpgresult = gpgme_op_keylist_start(m_gpgctx, NULL, secret);
const QString errorstring = QString::fromLocal8Bit(error); if (gpgresult != 0) {
kWarning() << errorstring; setError(gpgme_strerror(gpgresult));
return;
const QString errormessage = i18n("Error: %1", errorstring);
m_ui.statusbar->showMessage(errormessage);
m_ui.progressbar->setMinimum(0);
m_ui.progressbar->setMaximum(1);
} }
void KGPG::start() gpgme_key_t gpgkey;
{ gpgresult = gpgme_op_keylist_next(m_gpgctx, &gpgkey);
switch (m_mode) { while (gpgresult == 0) {
// TODO: implement gpgme_user_id_t gpguid = NULL;
default: { for (gpguid = gpgkey->uids; gpguid; gpguid = gpguid->next) {
break; KGPGKey kgpgkey;
kgpgkey.name = gpguid->name;
kgpgkey.email = gpguid->email;
kgpgkey.comment = gpguid->comment;
kgpgkey.uidhash = gpguid->uidhash;
kgpgkey.fpr = gpgkey->fpr;
kgpgkey.disabled = gpgkey->disabled;
kgpgkey.revoked = gpgkey->revoked;
kgpgkey.expired = gpgkey->expired;
kgpgkey.canencrypt = gpgkey->can_encrypt;
kgpgkey.cansign = gpgkey->can_sign;
m_keys.append(kgpgkey);
} }
gpgme_key_unref(gpgkey);
gpgresult = gpgme_op_keylist_next(m_gpgctx, &gpgkey);
} }
foreach (const KGPGKey &kgpgkey, m_keys) {
m_ui.keysbox->addItem(kgpgkey.uidhash);
}
// qDebug() << Q_FUNC_INFO << m_keys.size();
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@ -208,6 +292,7 @@ int main(int argc, char **argv)
if (args->isSet("encrypt")) { if (args->isSet("encrypt")) {
kgpg->setSource(args->getOption("encrypt")); kgpg->setSource(args->getOption("encrypt"));
kgpg->setMode(KGPG::EncryptMode); kgpg->setMode(KGPG::EncryptMode);
// kgpg->start();
} else if (args->isSet("decrypt")) { } else if (args->isSet("decrypt")) {
kgpg->setSource(args->getOption("decrypt")); kgpg->setSource(args->getOption("decrypt"));
kgpg->setMode(KGPG::DecryptMode); kgpg->setMode(KGPG::DecryptMode);
@ -215,6 +300,7 @@ int main(int argc, char **argv)
} else if (args->isSet("sign")) { } else if (args->isSet("sign")) {
kgpg->setSource(args->getOption("sign")); kgpg->setSource(args->getOption("sign"));
kgpg->setMode(KGPG::SignMode); kgpg->setMode(KGPG::SignMode);
// kgpg->start();
} else if (args->isSet("verify")) { } else if (args->isSet("verify")) {
kgpg->setSource(args->getOption("verify")); kgpg->setSource(args->getOption("verify"));
kgpg->setMode(KGPG::VerifyMode); kgpg->setMode(KGPG::VerifyMode);

View file

@ -31,6 +31,9 @@ struct KGPGKey
QByteArray name; QByteArray name;
QByteArray email; QByteArray email;
QByteArray comment; QByteArray comment;
QByteArray uidhash;
QByteArray fpr;
bool disabled;
bool revoked; bool revoked;
bool expired; bool expired;
bool canencrypt; bool canencrypt;
@ -54,10 +57,13 @@ public:
void setMode(const KGPGMode mode); void setMode(const KGPGMode mode);
void setSource(const QString &source); void setSource(const QString &source);
void setError(const char* const error); void setError(const char* const error);
void setError(const QString &error);
void start(); void start();
private: private:
void updateKeys(const gpgme_keylist_mode_t gpgmode, const bool secret);
Ui_KGPGWindow m_ui; Ui_KGPGWindow m_ui;
KGPGMode m_mode; KGPGMode m_mode;