#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gpg.h" #include "pass.h" #include "passphraseprovider.h" using namespace GpgME; using namespace QGpgME; Gpg::Gpg() { m_window = nullptr; initializeLibrary(); Gpg::initGpgConfig(); auto error = checkEngine(OpenPGP); if (error) { qDebug() << "Code Error : " << error.code(); qDebug() << "Error str : " << error.asString(); qFatal("GNUPG Engine check Fail"); } qDebug() << "GNUPG Engine Version is :" << engineInfo(OpenPGP).version(); qDebug() << "GNUPG Executable is :" << engineInfo(OpenPGP).fileName(); qDebug() << "GNUPG Home is :" << engineInfo(OpenPGP).homeDirectory(); } QString Gpg::initGpgHome() { QString path = QStandardPaths::writableLocation( QStandardPaths::AppDataLocation).append("/.gpghome"); QDir dir(path); if (!dir.exists()) { dir.mkpath("."); } return path; } QString Gpg::initGpgExec() { QString path = QDir::currentPath().append("/lib/bin/gpg"); QFileInfo file(path); if (!file.isFile()) { qFatal("GNUPGEXEC file not found !"); } if (!file.isExecutable()) { qFatal("GNUPGEXEC file not executable !"); } return path; } void Gpg::initGpgConfig() { auto home = initGpgHome(); auto exec = initGpgExec(); QFile agentConf(home + QStringLiteral("/gpg-agent.conf")); agentConf.remove(); agentConf.open(QIODevice::WriteOnly); agentConf.write("allow-loopback-pinentry"); agentConf.close(); gpgme_set_engine_info ( GPGME_PROTOCOL_OpenPGP, exec.toLocal8Bit().data(), home.toLocal8Bit().data() ); } QPair Gpg::decrypt(QByteArray cipherText) { auto job = openpgp()->decryptJob(); auto ctx = DecryptJob::context(job); auto provider = new UTPassphraseProvider; ctx->setPassphraseProvider(provider); ctx->setPinentryMode(Context::PinentryLoopback); QByteArray plain_text; auto decResult = job->exec(cipherText, plain_text); delete job; if (decResult.error()) { qWarning() << "something gone wrong on decrypt"; qDebug() << "Code Error : " << decResult.error().code(); qDebug() << "Error str : " << decResult.error().asString(); } return QPair(decResult.error(), QString::fromUtf8(plain_text)); } QPair Gpg::decryptFromFile(QString path) { qDebug() << "Decrypt from " << path; QFile file(path); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Can't open the File"; return QPair(Error(), QString());; } QByteArray cipherText = file.readAll(); file.close(); return decrypt(cipherText); } QPair Gpg::encrypt(QString str, QString uid, bool ascii_armor, bool text_mode) { qDebug() << "Encrypt to QByteArray"; auto keys = getKeys(uid); if (keys.first) { return QPair(keys.first, QByteArray()); } auto job = std::unique_ptr(openpgp()->encryptJob(ascii_armor, text_mode)); QByteArray cipherText; auto result = job->exec(keys.second, str.toUtf8(), Context::AlwaysTrust, cipherText); qDebug() << "Encrypted to QByteArray"; return QPair(result.error(), cipherText); } Error Gpg::encryptToFile(QString str, QString path, QString uid, bool ascii_armor, bool text_mode) { qDebug() << "Encrypting to file " << path; QFile file(path); if (!file.open(QIODevice::WriteOnly)) { qWarning() << "Can't open the file to write it" ; return Error(); } auto encrypt_ret = encrypt(str, uid, ascii_armor, text_mode); if (encrypt_ret.first) { file.write(encrypt_ret.second); } qDebug() << "Encrypting to file " << path; return encrypt_ret.first; } QPair> Gpg::getAllKeys ( bool remote, const bool include_sigs, bool validate ) { return getKeys(QString(""), remote, include_sigs, validate); } QPair> Gpg::getKeys(QString pattern_uid, bool remote, bool include_sigs, bool validate) { qDebug() << "Getting the keys " << pattern_uid; auto job = std::unique_ptr(openpgp()->keyListJob(remote, include_sigs, validate)); std::vector keys; auto result = job->exec(QStringList() << pattern_uid, false, keys); qDebug() << "Got the keys " << pattern_uid; return QPair>(result.error(), keys); } QPair Gpg::getKey(QString uid, bool remote, bool include_sigs, bool validate) { qDebug() << "Getting the key " << uid; auto keys = getKeys(uid, remote, include_sigs, validate); if (keys.first or keys.second.size() != 1) { qWarning() << "Bad id"; return QPair(keys.first, Key::null); } qDebug() << "Got the key " << uid; return QPair(keys.first, keys.second.front()); } Error Gpg::importKeysFromFile(QString path) { qDebug() << "Importing the key file" << path; qDebug() << "Decrypt from " << path; QFile file(path); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Can't open the File"; return Error(); } auto job = openpgp()->importJob(); auto ctx = ImportJob::context(job); auto provider = new UTPassphraseProvider; ctx->setPassphraseProvider(provider); ctx->setPinentryMode(Context::PinentryLoopback); auto result = job->exec(file.readAll()); qDebug() << "numImported" << result.numImported(); qDebug() << "numSecretKeysImported" << result.numSecretKeysImported(); qDebug() << "numSecretKeysConsidered" << result.numSecretKeysConsidered(); qDebug() << "numSecretKeysUnchanged" << result.numSecretKeysUnchanged(); qDebug() << "numUnchanged" << result.numUnchanged(); file.close(); delete job; delete provider; if (result.error()) { qWarning() << "Import go wrong"; qDebug() << "Code Error : " << result.error().code(); qDebug() << "Error str : " << result.error().asString(); } qDebug() << "Imported the key file" << path; return result.error(); } Error Gpg::deleteKeyId(QString uid) { qDebug() << "Deleting key id " << uid; auto key = getKey(uid); if (key.first) { return key.first; } auto ctx = std::unique_ptr(Context::createForProtocol(OpenPGP)); auto err = ctx->deleteKey(key.second, true); if (err) { qWarning() << "Delete go wrong"; qDebug() << "Code Error : " << err.code(); qDebug() << "Error str : " << err.asString(); return err; } qDebug() << "Deleted key id" << uid; return err; }