QCA Windows segfault KeyStoreManager



  • Hi,

    I need pgp support in my Qt Application. In linux everything is working but in windows I do not get it to work.
    First I have compiled QCA with my mingw64 compiler following this tutorial https://github.com/JPNaude/dev_notes/wiki/Using-the-Qt-Cryptographic-Architecture-with-Qt5.

    I am using Qt 5.4.2

    Everything seems to be ok but using the lib results in segfaults.
    The segfault appears in executing the line "QCA::KeyStoreManager::start();"

    #include <QtCore>
    #include <QtCrypto>
    
    int main(int argc, char **argv)
    {
    
        Q_UNUSED(argc);
        Q_UNUSED(argv);
    
        // the Initializer object sets things up, and
        // also does cleanup when it goes out of scope
        QCA::Initializer init;
    
        // must always check that an algorithm is supported before using it
        if(!QCA::isSupported("openpgp")) {
            qDebug() << "openpgp not supported!\n";
            return 0;
        } else {
            qDebug() << "openpgp supported!\n";
        }
    
        QCA::KeyStoreManager::start();
        QCA::KeyStoreManager ksm;
        ksm.waitForBusyFinished();
    
        return 0;
    
    }

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    First thing that comes to mind is missing QApplication



  • No that does not help.

    I have also tried to execute it if the eventloop is running.
    Same problem ... segfault in line KeyStoreManager::start()

    MainWindow::MainWindow()
    {
    
        button = new QPushButton("start", this);
    
        QObject::connect(button,&QPushButton::pressed,this,&MainWindow::onButtonPressed);
    
    }
    
    void MainWindow::onButtonPressed() {
    
        // must always check that an algorithm is supported before using it
        if(!QCA::isSupported("openpgp")) {
            qDebug() << "openpgp not supported!\n";
            QApplication::quit();
        } else {
            qDebug() << "openpgp supported!\n";
        }
    
        QCA::KeyStoreManager::start();
    
        qDebug() << "start";
    
        QCA::KeyStoreManager ksm;
        ksm.waitForBusyFinished();
    
        qDebug() << "finished";
    
    }
    

    The weired thing is that the same code is working on my linux machine. So I think it has to do with the compiled qca lib but I do not know how to find my issue or dive in the lib to find anything.

    I have tested the hex example of qca and this is working. So it is a specific problem with pgp only. (KeyStoreManager)


  • Lifetime Qt Champion

    Where are your GPG dlls located ?

    You are probably missing the path to them when running your application. If so, go to the Run part of the Project panel and add it to the PATH environment variable there.



  • I have installed Gpg4win and it is located in C:\Program Files (x86)\GNU\GnuPG

    There are some dll's in the subdir pub and bin
    For safety I have added the root dir, pub and bin to my Path variable.

    If I run the shipped tool

    qcatool-qt5.exe keystore list-stores
    

    it also crashes.


  • Lifetime Qt Champion

    If you run it from the command line you probably have the Qt dll's missing from PATH



  • Ok strange thing but doing a debug build of qca results in a working lib :D

    Dont know whats wrong with the normal build but adding the cmake flag CMAKE_BUILD_TYPE=Debug helped ?!?!


  • Lifetime Qt Champion

    Where you trying to run a debug build of your application against a release build of QCA ?



  • Yes, now it's clear ;)

    It does not come up a segfault if I link the debug lib to my debug build, same applies to the release build. Was not aware of this. I thought the lib is build in release mode and is a independetly thing that does not depend.

    But now calling my encrypt function results in an empty string :(
    The loop is finding the corresponding public key.

    QString PGPClient::encrypt(QString toAddress, QString message)
    {
    
    
        // must always check that an algorithm is supported before using it
        if(!QCA::isSupported("openpgp")) {
            qDebug() << "openpgp not supported!\n";
            QApplication::quit();
        } else {
            qDebug() << "openpgp supported!\n";
        }
    
        QCA::KeyStoreManager::start();
        QCA::KeyStoreManager ksm(this);
        ksm.waitForBusyFinished();
    
        QCA::KeyStore pgpks( QString("qca-gnupg"), &ksm );
    
        QCA::SecureMessageKey to;
        foreach(const QCA::KeyStoreEntry kse, pgpks.entryList()) {
    
            QString text = kse.name() + " // " + kse.id() + " // " + kse.storeId() + " // " + kse.storeName();
            qDebug() << text;
    
            if(kse.name().contains(toAddress)) {
                if(!kse.pgpPublicKey().isNull()) {
                    to.setPGPPublicKey(kse.pgpPublicKey());
                }
            }
    
        }
    
        qDebug();
        qDebug() << to.havePrivate();
        qDebug() << to.name();
    
        QCA::OpenPGP pgp;
        QCA::SecureMessage msg(&pgp);
    
        msg.setRecipient(to);
        msg.setFormat(QCA::SecureMessage::Ascii);
        
        qDebug() << "ok? " << msg.canSignAndEncrypt();
        qDebug() << message.toUtf8();
    
        msg.startEncrypt();
        msg.update(message.toUtf8());
        msg.end();
        msg.waitForFinished(10000);
    
        QByteArray crpt = msg.read();
        return QString::fromUtf8(crpt);
    
    }

  • Lifetime Qt Champion

    What output do you get from your qDebug statements ?



  • I only need a little of QCA so i decided to do it my own way and call the gpg binary myself.

    But how could it be otherwise, linux is working windows NOT.

    QString PGPProcess::encrypt(QString toAddress, QString message)
    {
    
        this->start(QStringList() << "--trust-model always" << "-a" << "-e" << "-r " + toAddress);
        this->waitForStarted(PROCESS_WAIT);
        this->write(message.toUtf8());
        this->waitForBytesWritten(PROCESS_WAIT);
        this->closeWriteChannel();
        this->waitForFinished(PROCESS_WAIT);
    
        if(this->exitCode()) {
            qDebug() << this->exitCode();
            return message;
        } else {
            return this->readAllStandardOutput();
        }
    
    }
    

    getting an errorcode 2. If I do the same sequence with the same arguments on the commandline it is working. Do not know whats wrong here.



  • Ok simply changing the argument QStringList to the following does the trick

    this->start(QStringList() << "--trust-model" << "always" << "-a" << "-e" << "-r" << toAddress);
    

    So every part as single String.


  • Lifetime Qt Champion

    Good, that's also a solution :)

    If you are still interested, you can try to re-run your QCA based application, with the PATH environment variable containing the path to the gpg executable. You can to that in Qt Creator by going to the Run part of the Project panel.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.