diff --git a/GpgMECWorker.cpp b/GpgMECWorker.cpp index 5ad087c..414b52c 100644 --- a/GpgMECWorker.cpp +++ b/GpgMECWorker.cpp @@ -9,6 +9,37 @@ #include "GpgMECWorker.h" +#ifdef DEVTIME + +/** + * This callback is never called when exporting private keys. + * From gpgme-1.14.0/tests/run-support.h + */ +gpgme_error_t passphrase_cb(void *opaque, const char *uid_hint, const char *passphrase_info, + int last_was_bad, int fd) +{ + int res; + char pass[] = "test_pwd\n"; + int passlen = strlen(pass); + int off = 0; + + (void) opaque; + (void) uid_hint; + (void) passphrase_info; + (void) last_was_bad; + + do + { + res = gpgme_io_write(fd, &pass[off], passlen - off); + if (res > 0) + off += res; + } + while (res > 0 && off != passlen); + + return off == passlen ? 0 : gpgme_error_from_errno(errno); +} +#endif + GpgMECWorker::GpgMECWorker() { gpgme_error_t c_err = gpgme_new(&c_ctx); @@ -36,4 +67,67 @@ bool GpgMECWorker::DeleteKey(const char * fpr, bool secret, GpgME::Error& e) return false; } return true; -} \ No newline at end of file +} + +#ifdef DEVTIME + +/** + * Much code here is obtained from gpgme-1.14.0/tests/run-export.c + * @param fpr + * @param e + * @return + */ +bool GpgMECWorker::ExportPrivateKey(const char* fpr, GpgME::Error& e) +{ + gpgme_key_t c_key; + gpgme_data_t out; + gpgme_set_armor(c_ctx, 1); + + gpgme_error_t c_err = gpgme_get_key(c_ctx, fpr, &c_key, true); + if (c_key == NULL) + { + e = GpgME::Error::fromCode(c_err); + return false; + } + + FILE * kFp = fopen("/tmp/data", "wb"); + if (kFp == NULL) + return false; + c_err = gpgme_data_new_from_stream(&out, kFp); + if (c_err != 0) + { + fclose(kFp); + e = GpgME::Error::fromCode(c_err); + return false; + } + + gpgme_key_t aKeys[2]; + aKeys[0] = c_key; + aKeys[1] = NULL; + + c_err = gpgme_set_pinentry_mode(c_ctx, GPGME_PINENTRY_MODE_LOOPBACK); + if (c_err != 0) + { + fclose(kFp); + e = GpgME::Error::fromCode(c_err); + return false; + } + gpgme_set_passphrase_cb(c_ctx, passphrase_cb, NULL); + + gpgme_export_mode_t flags = GPGME_EXPORT_MODE_SECRET; + c_err = gpgme_op_export_keys(c_ctx, aKeys, flags, out); + if (c_err != 0) + { + fclose(kFp); + gpgme_data_release(out); + e = GpgME::Error::fromCode(c_err); + return false; + } + fflush(NULL); + fclose(kFp); + + gpgme_data_release(out); + + return true; +} +#endif diff --git a/GpgMECWorker.h b/GpgMECWorker.h index cd39369..90c2d8e 100644 --- a/GpgMECWorker.h +++ b/GpgMECWorker.h @@ -31,6 +31,20 @@ public: */ bool DeleteKey(const char * fpr, bool secret, GpgME::Error& e); +#ifdef DEVTIME + /** + * Status : testing + * \n Result : fails to export a private key + * \n Reason : passphrase callback is never called + * \n With default pinentry mode, the password is requested normally + * and the private key is exported. But this can't be done on a web server. + * @param fpr + * @param e + * @return + */ + bool ExportPrivateKey(const char* fpr, GpgME::Error& e); +#endif + private: gpgme_ctx_t c_ctx; };