In the light of latest news (Snowden et all) it is very clear that all developers should really take care of safety of all communications that your application could perform. In the world of desktop application developments it is often is decided to be postponed and just use plain text protocols or so and later switch to use of SSL. Surely we should pay more attention to use ciphers when any need of QtNetwork is considered.

But what about using something different than just SSL? Let’s take a look at use of PGP in Qt Application. It is so good that there is great framework is already in place QCA (http://delta.affinix.com/qca/). All we need is just to take a look at API and find a simple way of making ciphers.

Let’s design very simple desktop application which can crypt some input text. I assume that have already installed GnuPG, generated keys, configured gpg-agent, installed and checked working pinentry-qt/pinentry-gtk(we are on linux now). Then you have installed qca and qca-gnupg

emerge --ask qca qca-gnupg

Just start Qt Creator, choose to make Qt Gui application, add to pro file a linking to qca:

LIBS += -L/usr/lib/qca2 -lqca
INCLUDEPATH += /usr/include/qca2/QtCrypto

And create simple form, connect button with our custom “encrypt” slots:

form

In main.cpp we just need to initialize QtCrypt:

#include <QtCrypto>
#include <QApplication>
#include "CryptWin.h"
int main(int argc, char *argv[]) {
	QCA::Initializer init;
	QApplication a(argc, argv);
	CryptWindow w;
	w.show();
	return a.exec();
}

Then in constructor of window we need to get a list of keys to initialize comboboxes:

	QCA::KeyStoreManager::start();
	QCA::KeyStoreManager ksm(this);
	ksm.waitForBusyFinished();

	QCA::KeyStore pgpks( QString("qca-gnupg"), &ksm );

	foreach(const QCA::KeyStoreEntry kse, pgpks.entryList()) {
		QString text = kse.name()+" "+kse.id();
		QVariant v; v.setValue(kse);
		ui->cb_to->addItem(text, v);
		if (!kse.pgpSecretKey().isNull())
			ui->cb_my->addItem(text, v);
	}

First(top) combobox gets all keys which have pgp secret keys – sender, second(bottom) combobox gets all keys that have only public part – receiver. Keys itself we embed into comboboxes by QVariant data argument.

Time to write a slot to react on “Encrypt” button:

void CryptWindow::encrypt() {
	QVariant v_my = ui->cb_my->itemData(ui->cb_my->currentIndex());
	QVariant v_to = ui->cb_to->itemData(ui->cb_to->currentIndex());
	if (!v_my.isValid()) { ui->pte_dst->setPlainText("Invalid src"); return; }
	if (!v_to.isValid()) { ui->pte_dst->setPlainText("Invalid dst"); return; }
	QCA::KeyStoreEntry kse_my = v_my.value<QCA::KeyStoreEntry>();
	QCA::KeyStoreEntry kse_to = v_to.value<QCA::KeyStoreEntry>();

	QCA::SecureMessageKey to;
	to.setPGPSecretKey( kse_my.pgpSecretKey() );
	to.setPGPPublicKey( kse_to.pgpPublicKey() );

	QCA::OpenPGP pgp;
	QCA::SecureMessage msg(&pgp);

	msg.setRecipient(to);
	msg.setFormat(QCA::SecureMessage::Ascii);
	msg.startEncrypt();
	msg.update(ui->pte_src->toPlainText().toUtf8());
	msg.end();
	msg.waitForFinished(2000);

	QByteArray crpt = msg.read();
	ui->pte_dst->setPlainText(QString::fromUtf8(crpt));
}

Try to run and test our simple demo application (sure you may be asked for your key password through gpg-agent):

result

Isn’t it so simple and cool? As next the cipher is to be used with QtNetwork, etc…

FILES:

Crypt.pro

main.cpp

CryptWin.ui

CryptWin.h

CryptWin.cpp