Index: kdebase-runtime-4.3.5/kwalletd/backend/backendpersisthandler.h
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/backend/backendpersisthandler.h
@@ -0,0 +1,86 @@
+/**
+  * This file is part of the KDE project
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Library General Public
+  * License version 2 as published by the Free Software Foundation.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Library General Public License for more details.
+  *
+  * You should have received a copy of the GNU Library General Public License
+  * along with this library; see the file COPYING.LIB.  If not, write to
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  * Boston, MA 02110-1301, USA.
+  */
+#ifndef BACKENDPERSISTHANDLER_H
+#define BACKENDPERSISTHANDLER_H
+
+#define KWMAGIC_LEN 12
+
+#include <qwindowdefs.h>
+
+class QFile;
+class KSaveFile;
+namespace KWallet {
+
+class Backend;
+
+enum BackendCipherType {
+    BACKEND_CIPHER_UNKNOWN,  /// this is used by freshly allocated wallets
+    BACKEND_CIPHER_BLOWFISH, /// use the legacy blowfish cipher type
+#ifdef HAVE_QGPGME
+    BACKEND_CIPHER_GPG       /// use GPG backend to encrypt wallet contents
+#endif // HAVE_QGPGME
+};
+
+
+class BackendPersistHandler {
+protected:
+    BackendPersistHandler() {}
+public:
+    virtual ~BackendPersistHandler() {}
+    /**
+     * This is a factory method used to get an instance of the backend suitable
+     * for reading/writing using the given cipher type
+     *
+     * @param cypherType indication of the backend that should be returned
+     * @return a pointer to an instance of the requested handler type. No need to delete this pointer, it's lifetime is taken care of by this factory
+     */
+    static BackendPersistHandler *getPersistHandler(BackendCipherType cipherType);
+    static BackendPersistHandler *getPersistHandler(char magicBuf[KWMAGIC_LEN]);
+
+    virtual int write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w) =0;
+    virtual int read(Backend* wb, QFile& sf, WId w) =0;
+};
+
+
+class BlowfishPersistHandler : public BackendPersistHandler {
+public:
+    explicit BlowfishPersistHandler(bool useECBforReading =false) : _useECBforReading(useECBforReading) {}
+    virtual ~BlowfishPersistHandler() {}
+
+    virtual int write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w);
+    virtual int read(Backend* wb, QFile& sf, WId w);
+private:
+    bool _useECBforReading;
+};
+
+#ifdef HAVE_QGPGME
+class GpgPersistHandler : public BackendPersistHandler {
+public:
+    GpgPersistHandler() {}
+    virtual ~GpgPersistHandler() {}
+
+    virtual int write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w);
+    virtual int read(Backend* wb, QFile& sf, WId w);
+};
+#endif // HAVE_QGPGME
+
+} // namespace
+
+#endif // BACKENDPERSISTHANDLER_H
+
Index: kdebase-runtime-4.3.5/kwalletd/backend/backendpersisthandler.cpp
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/backend/backendpersisthandler.cpp
@@ -0,0 +1,749 @@
+/**
+  * This file is part of the KDE project
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Library General Public
+  * License version 2 as published by the Free Software Foundation.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Library General Public License for more details.
+  *
+  * You should have received a copy of the GNU Library General Public License
+  * along with this library; see the file COPYING.LIB.  If not, write to
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  * Boston, MA 02110-1301, USA.
+  */
+
+#include <QIODevice>
+#include <QFile>
+#include <QTextDocument>
+#include <assert.h>
+#include <ksavefile.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <klocalizedstring.h>
+#ifdef HAVE_QGPGME
+#include <gpgme.h>
+#include <gpgme++/context.h>
+#include <gpgme++/key.h>
+#include <gpgme++/keylistresult.h>
+#include <gpgme++/data.h>
+#include <gpgme++/encryptionresult.h>
+#include <gpgme++/decryptionresult.h>
+#endif
+#include "backendpersisthandler.h"
+#include "kwalletbackend.h"
+#include "blowfish.h"
+#include "sha1.h"
+#include "cbc.h"
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+#include <wincrypt.h>
+#endif
+
+#define KWALLET_CIPHER_BLOWFISH_ECB 0 // this was the old KWALLET_CIPHER_BLOWFISH_CBC
+#define KWALLET_CIPHER_3DES_CBC     1 // unsupported
+#define KWALLET_CIPHER_GPG          2
+#define KWALLET_CIPHER_BLOWFISH_CBC 3
+
+#define KWALLET_HASH_SHA1       0
+#define KWALLET_HASH_MD5        1 // unsupported
+#define KWALLET_HASH_PBKDF2_SHA512 2 // used when using kwallet with pam or since 4.13 version
+
+namespace KWallet {
+
+static int getRandomBlock(QByteArray& randBlock) {
+
+#ifdef Q_OS_WIN //krazy:exclude=cpp
+
+    // Use windows crypto API to get randomness on win32
+    // HACK: this should be done using qca
+    HCRYPTPROV hProv;
+
+    if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
+        CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) return -1; // couldn't get random data
+
+    if (!CryptGenRandom(hProv, static_cast<DWORD>(randBlock.size()),
+        (BYTE*)randBlock.data())) {
+        return -3; // read error
+    }
+
+    // release the crypto context
+    CryptReleaseContext(hProv, 0);
+
+    return randBlock.size();
+
+#else
+
+    // First try /dev/urandom
+    if (QFile::exists("/dev/urandom")) {
+        QFile devrand("/dev/urandom");
+        if (devrand.open(QIODevice::ReadOnly)) {
+            int rc = devrand.read(randBlock.data(), randBlock.size());
+
+            if (rc != randBlock.size()) {
+                return -3;      // not enough data read
+            }
+
+            return 0;
+        }
+    }
+
+    // If that failed, try /dev/random
+    // FIXME: open in noblocking mode!
+    if (QFile::exists("/dev/random")) {
+        QFile devrand("/dev/random");
+        if (devrand.open(QIODevice::ReadOnly)) {
+            int rc = 0;
+            int cnt = 0;
+
+            do {
+                int rc2 = devrand.read(randBlock.data() + rc, randBlock.size());
+
+                if (rc2 < 0) {
+                    return -3;  // read error
+                }
+
+                rc += rc2;
+                cnt++;
+                if (cnt > randBlock.size()) {
+                    return -4;  // reading forever?!
+                }
+            } while(rc < randBlock.size());
+
+            return 0;
+        }
+    }
+
+    // EGD method
+    QString randFilename = QString::fromLocal8Bit(qgetenv("RANDFILE"));
+    if (!randFilename.isEmpty()) {
+        if (QFile::exists(randFilename)) {
+            QFile devrand(randFilename);
+            if (devrand.open(QIODevice::ReadOnly)) {
+                int rc = devrand.read(randBlock.data(), randBlock.size());
+                if (rc != randBlock.size()) {
+                    return -3;      // not enough data read
+                }
+                return 0;
+            }
+        }
+    }
+
+    // Couldn't get any random data!!
+    return -1;
+
+#endif
+}
+
+
+
+static BlowfishPersistHandler *blowfishHandler =0;
+#ifdef HAVE_QGPGME
+static GpgPersistHandler *gpgHandler =0;
+#endif // HAVE_QGPGME
+
+BackendPersistHandler *BackendPersistHandler::getPersistHandler(BackendCipherType cipherType)
+{
+    switch (cipherType){
+        case BACKEND_CIPHER_BLOWFISH:
+            if (0 == blowfishHandler)
+                blowfishHandler = new BlowfishPersistHandler;
+            return blowfishHandler;
+#ifdef HAVE_QGPGME
+        case BACKEND_CIPHER_GPG:
+            if (0 == gpgHandler)
+                gpgHandler = new GpgPersistHandler;
+            return gpgHandler;
+#endif // HAVE_QGPGME
+        default:
+            Q_ASSERT(0);
+            return 0;
+    }
+}
+
+BackendPersistHandler *BackendPersistHandler::getPersistHandler(char magicBuf[12])
+{
+    if ((magicBuf[2] == KWALLET_CIPHER_BLOWFISH_ECB || magicBuf[2] == KWALLET_CIPHER_BLOWFISH_CBC) &&
+        (magicBuf[3] == KWALLET_HASH_SHA1 || magicBuf[3] == KWALLET_HASH_PBKDF2_SHA512)) {
+        if (0 == blowfishHandler) {
+            bool useECBforReading = magicBuf[2] == KWALLET_CIPHER_BLOWFISH_ECB;
+            if (useECBforReading) {
+                qDebug() << "this wallet uses ECB encryption. It'll be converted to CBC on next save.";
+            }
+            blowfishHandler = new BlowfishPersistHandler(useECBforReading);
+        }
+        return blowfishHandler;
+    }
+#ifdef HAVE_QGPGME
+    if (magicBuf[2] == KWALLET_CIPHER_GPG &&
+        magicBuf[3] == 0) {
+        if (0 == gpgHandler)
+            gpgHandler = new GpgPersistHandler;
+        return gpgHandler;
+    }
+#endif // HAVE_QGPGME
+    return 0;    // unknown cipher or hash
+}
+
+int BlowfishPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WId)
+{
+    assert(wb->_cipherType == BACKEND_CIPHER_BLOWFISH);
+
+    if (_useECBforReading) {
+        qDebug() << "This wallet used ECB and is now saved using CBC";
+        _useECBforReading = false;
+    }
+
+    version[2] = KWALLET_CIPHER_BLOWFISH_CBC;
+    if(!wb->_useNewHash) {
+        version[3] = KWALLET_HASH_SHA1;
+    } else {
+        version[3] = KWALLET_HASH_PBKDF2_SHA512;//Since 4.13 we always use PBKDF2_SHA512
+    }
+
+    if (sf.write(version, 4) != 4) {
+        sf.abort();
+        return -4; // write error
+    }
+
+    // Holds the hashes we write out
+    QByteArray hashes;
+    QDataStream hashStream(&hashes, QIODevice::WriteOnly);
+    KMD5 md5;
+    hashStream << static_cast<quint32>(wb->_entries.count());
+
+    // Holds decrypted data prior to encryption
+    QByteArray decrypted;
+
+    // FIXME: we should estimate the amount of data we will write in each
+    // buffer and resize them approximately in order to avoid extra
+    // resizes.
+
+    // populate decrypted
+    QDataStream dStream(&decrypted, QIODevice::WriteOnly);
+    for (Backend::FolderMap::ConstIterator i = wb->_entries.constBegin(); i != wb->_entries.constEnd(); ++i) {
+        dStream << i.key();
+        dStream << static_cast<quint32>(i.value().count());
+
+        md5.reset();
+        md5.update(i.key().toUtf8());
+        hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
+        hashStream << static_cast<quint32>(i.value().count());
+
+        for (Backend::EntryMap::ConstIterator j = i.value().constBegin(); j != i.value().constEnd(); ++j) {
+            dStream << j.key();
+            dStream << static_cast<qint32>(j.value()->type());
+            dStream << j.value()->value();
+
+            md5.reset();
+            md5.update(j.key().toUtf8());
+            hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
+        }
+    }
+
+    if (sf.write(hashes, hashes.size()) != hashes.size()) {
+        sf.abort();
+        return -4; // write error
+    }
+
+    // calculate the hash of the file
+    SHA1 sha;
+    BlowFish _bf;
+    CipherBlockChain bf(&_bf);
+
+    sha.process(decrypted.data(), decrypted.size());
+
+    // prepend and append the random data
+    QByteArray wholeFile;
+    long blksz = bf.blockSize();
+    long newsize = decrypted.size() +
+               blksz            +    // encrypted block
+               4                +    // file size
+               20;      // size of the SHA hash
+
+    int delta = (blksz - (newsize % blksz));
+    newsize += delta;
+    wholeFile.resize(newsize);
+
+    QByteArray randBlock;
+    randBlock.resize(blksz+delta);
+    if (getRandomBlock(randBlock) < 0) {
+        sha.reset();
+        decrypted.fill(0);
+        sf.abort();
+        return -3;      // Fatal error: can't get random
+    }
+
+    for (int i = 0; i < blksz; i++) {
+        wholeFile[i] = randBlock[i];
+    }
+
+    for (int i = 0; i < 4; i++) {
+        wholeFile[(int)(i+blksz)] = (decrypted.size() >> 8*(3-i))&0xff;
+    }
+
+    for (int i = 0; i < decrypted.size(); i++) {
+        wholeFile[(int)(i+blksz+4)] = decrypted[i];
+    }
+
+    for (int i = 0; i < delta; i++) {
+        wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)];
+    }
+
+    const char *hash = (const char *)sha.hash();
+    for (int i = 0; i < 20; i++) {
+        wholeFile[(int)(newsize - 20 + i)] = hash[i];
+    }
+
+    sha.reset();
+    decrypted.fill(0);
+
+    // encrypt the data
+    if (!bf.setKey(wb->_passhash.data(), wb->_passhash.size() * 8)) {
+        wholeFile.fill(0);
+        sf.abort();
+        return -2; // encrypt error
+    }
+
+    int rc = bf.encrypt(wholeFile.data(), wholeFile.size());
+    if (rc < 0) {
+        wholeFile.fill(0);
+        sf.abort();
+        return -2;  // encrypt error
+    }
+
+    // write the file
+    if (sf.write(wholeFile, wholeFile.size()) != wholeFile.size()) {
+        wholeFile.fill(0);
+        sf.abort();
+        return -4; // write error
+    }
+    if (!sf.finalize()) {
+        kDebug() << "WARNING: wallet sync to disk failed! KSaveFile status was " << sf.errorString();
+        wholeFile.fill(0);
+        return -4; // write error
+    }
+
+    wholeFile.fill(0);
+
+    return 0;
+}
+
+
+int BlowfishPersistHandler::read(Backend* wb, QFile& db, WId)
+{
+    wb->_cipherType = BACKEND_CIPHER_BLOWFISH;
+    wb->_hashes.clear();
+    // Read in the hashes
+    QDataStream hds(&db);
+    quint32 n;
+    hds >> n;
+    if (n > 0xffff) { // sanity check
+        return -43;
+    }
+
+    for (size_t i = 0; i < n; ++i) {
+        KMD5::Digest d, d2; // judgment day
+        MD5Digest ba;
+        QMap<MD5Digest,QList<MD5Digest> >::iterator it;
+        quint32 fsz;
+        if (hds.atEnd()) return -43;
+        hds.readRawData(reinterpret_cast<char *>(d), 16);
+        hds >> fsz;
+        ba = MD5Digest(reinterpret_cast<char *>(d));
+        it = wb->_hashes.insert(ba, QList<MD5Digest>());
+        for (size_t j = 0; j < fsz; ++j) {
+            hds.readRawData(reinterpret_cast<char *>(d2), 16);
+            ba = MD5Digest(reinterpret_cast<char *>(d2));
+            (*it).append(ba);
+        }
+    }
+
+    // Read in the rest of the file.
+    QByteArray encrypted = db.readAll();
+    assert(encrypted.size() < db.size());
+
+    BlowFish _bf;
+    CipherBlockChain bf(&_bf, _useECBforReading);
+    int blksz = bf.blockSize();
+    if ((encrypted.size() % blksz) != 0) {
+        return -5;     // invalid file structure
+    }
+
+    bf.setKey((void *)wb->_passhash.data(), wb->_passhash.size()*8);
+
+    if (!encrypted.data()) {
+        wb->_passhash.fill(0);
+        encrypted.fill(0);
+        return -7; // file structure error
+    }
+
+    int rc = bf.decrypt(encrypted.data(), encrypted.size());
+    if (rc < 0) {
+        wb->_passhash.fill(0);
+        encrypted.fill(0);
+        return -6;  // decrypt error
+    }
+
+    const char *t = encrypted.data();
+
+    // strip the leading data
+    t += blksz;    // one block of random data
+
+    // strip the file size off
+    long fsize = 0;
+
+    fsize |= (long(*t) << 24) & 0xff000000;
+    t++;
+    fsize |= (long(*t) << 16) & 0x00ff0000;
+    t++;
+    fsize |= (long(*t) <<  8) & 0x0000ff00;
+    t++;
+    fsize |= long(*t) & 0x000000ff;
+    t++;
+
+    if (fsize < 0 || fsize > long(encrypted.size()) - blksz - 4) {
+        //kDebug() << "fsize: " << fsize << " encrypted.size(): " << encrypted.size() << " blksz: " << blksz;
+        encrypted.fill(0);
+        return -9;         // file structure error.
+    }
+
+    // compute the hash ourself
+    SHA1 sha;
+    sha.process(t, fsize);
+    const char *testhash = (const char *)sha.hash();
+
+    // compare hashes
+    int sz = encrypted.size();
+    for (int i = 0; i < 20; i++) {
+        if (testhash[i] != encrypted[sz - 20 + i]) {
+            encrypted.fill(0);
+            sha.reset();
+            return -8;         // hash error.
+        }
+    }
+
+    sha.reset();
+
+    // chop off the leading blksz+4 bytes
+    QByteArray tmpenc(encrypted.data()+blksz+4, fsize);
+    encrypted = tmpenc;
+    tmpenc.fill(0);
+
+    // Load the data structures up
+    QDataStream eStream(encrypted);
+
+    while (!eStream.atEnd()) {
+        QString folder;
+        quint32 n;
+
+        eStream >> folder;
+        eStream >> n;
+
+        // Force initialisation
+        wb->_entries[folder].clear();
+
+        for (size_t i = 0; i < n; ++i) {
+            QString key;
+            KWallet::Wallet::EntryType et = KWallet::Wallet::Unknown;
+            Entry *e = new Entry;
+            eStream >> key;
+            qint32 x = 0; // necessary to read properly
+            eStream >> x;
+            et = static_cast<KWallet::Wallet::EntryType>(x);
+
+            switch (et) {
+            case KWallet::Wallet::Password:
+            case KWallet::Wallet::Stream:
+            case KWallet::Wallet::Map:
+            break;
+            default: // Unknown entry
+                delete e;
+                continue;
+            }
+
+            QByteArray a;
+            eStream >> a;
+            e->setValue(a);
+            e->setType(et);
+            e->setKey(key);
+            wb->_entries[folder][key] = e;
+        }
+    }
+
+    wb->_open = true;
+    encrypted.fill(0);
+    return 0;
+}
+
+#ifdef HAVE_QGPGME
+GpgME::Error initGpgME()
+{
+    GpgME::Error err;
+    static bool alreadyInitialized = false;
+    if (!alreadyInitialized) {
+        GpgME::initializeLibrary();
+        err = GpgME::checkEngine(GpgME::OpenPGP);
+        if (err){
+            kDebug() << "OpenPGP not supported!";
+        }
+        alreadyInitialized = true;
+    }
+    return err;
+}
+
+int GpgPersistHandler::write(Backend* wb, KSaveFile& sf, QByteArray& version, WId w)
+{
+    version[2] = KWALLET_CIPHER_GPG;
+    version[3] = 0;
+    if (sf.write(version, 4) != 4) {
+        sf.abort();
+        return -4; // write error
+    }
+
+    GpgME::Error err = initGpgME();
+    if (err) {
+        kDebug() << "initGpgME returned " << err.code();
+        KMessageBox::errorWId( w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to save the wallet <b>%1</b>. Error code is <b>%2</b>. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name), err.code()));
+        sf.abort();
+        return -5;
+    }
+
+    boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+    if (0 == ctx) {
+        kDebug() << "Cannot setup OpenPGP context!";
+        KMessageBox::errorWId(w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to save the wallet <b>%1</b>. Please fix your system configuration, then try again!</qt>"), Qt::escape(wb->_name));
+        return -6;
+    }
+
+    assert(wb->_cipherType == BACKEND_CIPHER_GPG);
+
+    QByteArray hashes;
+    QDataStream hashStream(&hashes, QIODevice::WriteOnly);
+    KMD5 md5;
+    hashStream << static_cast<quint32>(wb->_entries.count());
+
+    QByteArray values;
+    QDataStream valueStream(&values, QIODevice::WriteOnly);
+    Backend::FolderMap::ConstIterator i = wb->_entries.constBegin();
+    Backend::FolderMap::ConstIterator ie = wb->_entries.constEnd();
+    for ( ; i != ie; ++i) {
+        valueStream << i.key();
+        valueStream << static_cast<quint32>(i.value().count());
+
+        md5.reset();
+        md5.update(i.key().toUtf8());
+        hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
+        hashStream << static_cast<quint32>(i.value().count());
+
+        Backend::EntryMap::ConstIterator j = i.value().constBegin();
+        Backend::EntryMap::ConstIterator je = i.value().constEnd();
+        for (; j != je; ++j) {
+            valueStream << j.key();
+            valueStream << static_cast<qint32>(j.value()->type());
+            valueStream << j.value()->value();
+
+            md5.reset();
+            md5.update(j.key().toUtf8());
+            hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
+        }
+    }
+
+    QByteArray dataBuffer;
+    QDataStream dataStream(&dataBuffer, QIODevice::WriteOnly);
+    QString keyID(wb->_gpgKey.keyID());
+    dataStream << keyID;
+    dataStream << hashes;
+    dataStream << values;
+
+    GpgME::Data decryptedData(dataBuffer.data(), dataBuffer.size(), false);
+    GpgME::Data encryptedData;
+    std::vector< GpgME::Key > keys;
+    keys.push_back(wb->_gpgKey);
+    GpgME::EncryptionResult res = ctx->encrypt(keys, decryptedData, encryptedData, GpgME::Context::None);
+    if (res.error()){
+        int gpgerr = res.error().code();
+        KMessageBox::errorWId( w, i18n("<qt>Encryption error while attempting to save the wallet <b>%1</b>. Error code is <b>%2 (%3)</b>. Please fix your system configuration, then try again!</qt>",
+                                       Qt::escape(wb->_name), gpgerr, gpgme_strerror(gpgerr)));
+        kDebug() << "GpgME encryption error: " << res.error().code();
+        sf.abort();
+        return -7;
+    }
+
+    char buffer[4096];
+    ssize_t bytes =0;
+    encryptedData.seek(0, SEEK_SET);
+    while (bytes = encryptedData.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
+        if (sf.write(buffer, bytes) != bytes){
+            KMessageBox::errorWId( w, i18n("<qt>File handling error while attempting to save the wallet <b>%1</b>. Error was <b>%2</b>. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name), sf.errorString()));
+            sf.abort();
+            return -4; // write error
+        }
+    }
+
+    return 0;
+}
+
+int GpgPersistHandler::read(Backend* wb, QFile& sf, WId w)
+{
+    GpgME::Error err = initGpgME();
+    if (err){
+        KMessageBox::errorWId( w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to open the wallet <b>%1</b>. Error code is <b>%2</b>. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name), err.code()));
+        return -1;
+    }
+
+    wb->_cipherType = BACKEND_CIPHER_GPG;
+    wb->_hashes.clear();
+
+    // the remainder of the file is GPG encrypted. Let's decrypt it
+    GpgME::Data encryptedData;
+    char buffer[4096];
+    ssize_t bytes = 0;
+    while (bytes = sf.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
+        encryptedData.write(buffer, bytes);
+    }
+
+  retry_label:
+    boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+    if (0 == ctx) {
+        KMessageBox::errorWId(w, i18n("<qt>Error when attempting to initialize OpenPGP while attempting to open the wallet <b>%1</b>. Please fix your system configuration, then try again!</qt>", Qt::escape(wb->_name)));
+        kDebug() << "Cannot setup OpenPGP context!";
+        return -1;
+    }
+
+    GpgME::Data decryptedData;
+    encryptedData.seek(0, SEEK_SET);
+    GpgME::DecryptionResult res = ctx->decrypt(encryptedData, decryptedData);
+    if (res.error()){
+        kDebug() << "Error decrypting message: " << res.error().asString() << ", code " << res.error().code() << ", source " << res.error().source();
+        KGuiItem btnRetry(i18n("Retry"));
+        // FIXME the logic here should be a little more elaborate; a dialog box should be used with "retry", "cancel", but also "troubleshoot" with options to show card status and to kill scdaemon
+        int userChoice = KMessageBox::warningYesNoWId(w, i18n("<qt>Error when attempting to decrypt the wallet <b>%1</b> using GPG. If you're using a SmartCard, please ensure it's inserted then try again.<br><br>GPG error was <b>%2</b></qt>", Qt::escape(wb->_name), res.error().asString()),
+            i18n("kwalletd GPG backend"), btnRetry, KStandardGuiItem::cancel());
+        if (userChoice == KMessageBox::Yes) {
+            decryptedData.seek(0, SEEK_SET);
+            goto retry_label;
+        }
+        return -1;
+    }
+
+    decryptedData.seek(0, SEEK_SET);
+    QByteArray dataBuffer;
+    while (bytes = decryptedData.read(buffer, sizeof(buffer)/sizeof(buffer[0]))){
+        dataBuffer.append(buffer, bytes);
+    }
+
+    // load the wallet from the decrypted data
+    QDataStream dataStream(dataBuffer);
+    QString keyID;
+    QByteArray hashes;
+    QByteArray values;
+    dataStream >> keyID;
+    dataStream >> hashes;
+    dataStream >> values;
+
+    // locate the GPG key having the ID found inside the file. This will be needed later, when writing changes to disk.
+    QDataStream fileStream(&sf);
+    fileStream.unsetDevice();
+    kDebug() << "This wallet was encrypted using GPG key with ID " << keyID;
+
+    ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+    std::vector< GpgME::Key > keys;
+    int row =0;
+    err = ctx->startKeyListing();
+    while (!err) {
+        GpgME::Key k = ctx->nextKey(err);
+        if (err)
+            break;
+        if (keyID == k.keyID()){
+            kDebug() << "The key was found.";
+            wb->_gpgKey = k;
+            break;
+        }
+    }
+    ctx->endKeyListing();
+    if (wb->_gpgKey.isNull()){
+        KMessageBox::errorWId(w, i18n("<qt>Error when attempting to open the wallet <b>%1</b>. The wallet was encrypted using the GPG Key ID <b>%2</b> but this key was not found on your system.</qt>", Qt::escape(wb->_name), keyID));
+        return -1;
+    }
+
+
+    QDataStream hashStream(hashes);
+    QDataStream valueStream(values);
+
+    quint32 hashCount;
+    hashStream >> hashCount;
+    if (hashCount > 0xFFFF) {
+        return -43;
+    }
+
+    quint32 folderCount = hashCount;
+    while (hashCount--){
+        KMD5::Digest d;
+        hashStream.readRawData(reinterpret_cast<char *>(d), 16);
+
+        quint32 folderSize;
+        hashStream >> folderSize;
+
+        MD5Digest ba = MD5Digest(reinterpret_cast<char *>(d));
+        QMap<MD5Digest, QList<MD5Digest> >::iterator it = wb->_hashes.insert(ba, QList<MD5Digest>());
+        while (folderSize--){
+            KMD5::Digest d2;
+            hashStream.readRawData(reinterpret_cast<char *>(d2), 16);
+            ba = MD5Digest(reinterpret_cast<char *>(d2));
+            (*it).append(ba);
+        }
+    }
+
+    while (folderCount--){
+        QString folder;
+        valueStream >> folder;
+
+        quint32 entryCount;
+        valueStream >> entryCount;
+
+        wb->_entries[folder].clear();
+
+        while (entryCount--){
+            KWallet::Wallet::EntryType et = KWallet::Wallet::Unknown;
+            Entry *e = new Entry;
+
+            QString key;
+            valueStream >> key;
+
+            qint32 x =0; // necessary to read properly
+            valueStream >> x;
+            et = static_cast<KWallet::Wallet::EntryType>(x);
+
+            switch (et) {
+            case KWallet::Wallet::Password:
+            case KWallet::Wallet::Stream:
+            case KWallet::Wallet::Map:
+            break;
+            default: // Unknown entry
+                delete e;
+                continue;
+            }
+
+            QByteArray a;
+            valueStream >> a;
+            e->setValue(a);
+            e->setType(et);
+            e->setKey(key);
+            wb->_entries[folder][key] = e;
+        }
+    }
+
+    wb->_open = true;
+
+    return 0;
+}
+#endif // HAVE_QGPGME
+
+} // namespace
+
Index: kdebase-runtime-4.3.5/kwalletd/backend/cbc.cc
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/backend/cbc.cc
+++ kdebase-runtime-4.3.5/kwalletd/backend/cbc.cc
@@ -17,133 +17,196 @@
    Boston, MA 02110-1301, USA.
 */
 
-
 #include "cbc.h"
 #include <string.h>
+#include <kdebug.h>
 
-
-
-CipherBlockChain::CipherBlockChain(BlockCipher *cipher) : _cipher(cipher) {
-	_next = 0L;
-	_register = 0L;
-	_len = -1;
-	_reader = _writer = 0L;
-	if (cipher) {
-		_blksz = cipher->blockSize();
-	}
-}
-
-
-CipherBlockChain::~CipherBlockChain() {
-	delete[] (char *)_register;
-	_register = 0L;
-	delete[] (char *)_next;
-	_next = 0L;
-}
-
-
-bool CipherBlockChain::setKey(void *key, int bitlength) {
-	if (_cipher) {
-		return _cipher->setKey(key, bitlength);
-	}
-	return false;
-}
-
-
-int CipherBlockChain::keyLen() const {
-	if (_cipher) {
-		return _cipher->keyLen();
-	}
-	return -1;
-}
-
-
-bool CipherBlockChain::variableKeyLen() const {
-	if (_cipher) {
-		return _cipher->variableKeyLen();
-	}
-	return false;
-}
-
-
-bool CipherBlockChain::readyToGo() const {
-	if (_cipher) {
-		return _cipher->readyToGo();
-	}
-	return false;
-}
-
-
-int CipherBlockChain::encrypt(void *block, int len) {
-	if (_cipher && !_reader) {
-		int rc;
-
-		_writer |= 1;
-
-		if (!_register) {
-			_register = new unsigned char[len];
-			_len = len;
-			memset(_register, 0, len);
-		} else if (len > _len) {
-			return -1;
-		}
-
-		// This might be optimizable
-		char *tb = (char *)block;
-		for (int i = 0; i < len; i++) {
-			tb[i] ^= ((char *)_register)[i];
-		}
-
-		rc = _cipher->encrypt(block, len);
-
-		if (rc != -1) {
-			memcpy(_register, block, len);
-		}
-
-		return rc;
-	}
-	return -1;
-}
-
-
-int CipherBlockChain::decrypt(void *block, int len) {
-	if (_cipher && !_writer) {
-		int rc;
-
-		_reader |= 1;
-
-		if (!_register) {
-			_register = new unsigned char[len];
-			_len = len;
-			memset(_register, 0, len);
-		} else if (len > _len) {
-			return -1;
-		} 
-
-		if (!_next)
-			_next = new unsigned char[_len];
-		memcpy(_next, block, _len);
-
-		rc = _cipher->decrypt(block, len);
-
-		if (rc != -1) {
-			// This might be optimizable
-			char *tb = (char *)block;
-			for (int i = 0; i < len; i++) {
-				tb[i] ^= ((char *)_register)[i];
-			}
-		}
-
-		void *temp;
-		temp = _next;
-		_next = _register;
-		_register = temp;
-
-		return rc;
-	}
-	return -1;
+CipherBlockChain::CipherBlockChain(BlockCipher *cipher, bool useECBforReading) :
+    _cipher(cipher)
+    , _useECBforReading(useECBforReading)
+{
+    _next = 0L;
+    _register = 0L;
+    _len = -1;
+    _reader = _writer = 0L;
+    if (cipher) {
+        _blksz = cipher->blockSize();
+    }
+}
+
+CipherBlockChain::~CipherBlockChain()
+{
+    delete[](char *)_register;
+    _register = 0L;
+    delete[](char *)_next;
+    _next = 0L;
+}
+
+bool CipherBlockChain::setKey(void *key, int bitlength)
+{
+    if (_cipher) {
+        return _cipher->setKey(key, bitlength);
+    }
+    return false;
+}
+
+int CipherBlockChain::keyLen() const
+{
+    if (_cipher) {
+        return _cipher->keyLen();
+    }
+    return -1;
+}
+
+bool CipherBlockChain::variableKeyLen() const
+{
+    if (_cipher) {
+        return _cipher->variableKeyLen();
+    }
+    return false;
+}
+
+bool CipherBlockChain::readyToGo() const
+{
+    if (_cipher) {
+        return _cipher->readyToGo();
+    }
+    return false;
+}
+
+void CipherBlockChain::initRegister() {
+    if (_register == 0L) {
+        size_t registerLen = _cipher->blockSize();
+        _register = new unsigned char[registerLen];
+        _len = registerLen;
+    }
+    memset(_register, 0, _len);
+}
+
+int CipherBlockChain::encrypt(void *block, int len)
+{
+    if (_cipher && !_reader) {
+        int rc;
+
+        _writer |= 1;
+
+        initRegister();
+
+        if ((len % _len) >0) {
+            kDebug() << "Block length given encrypt (" << len << ") is not a multiple of " << _len;
+            return -1;
+        }
+
+        char *elemBlock = static_cast<char*>(block);
+        for (int b = 0; b < len/_len; b++) {
+
+            // This might be optimizable
+            char *tb = static_cast<char*>(elemBlock);
+            for (int i = 0; i < _len; i++) {
+                *tb++ ^= ((char *)_register)[i];
+            }
+
+            rc = _cipher->encrypt(elemBlock, _len);
+
+            if (rc != -1) {
+                memcpy(_register, elemBlock, _len);
+            }
+            elemBlock += _len;
+        }
+
+        return rc;
+    }
+    return -1;
+}
+
+// This is the old decrypt method, that was decrypting using ECB
+// instead of CBC
+int CipherBlockChain::decryptECB(void *block, int len) {
+    if (_cipher && !_writer) {
+        int rc;
+
+        _reader |= 1;
+
+        if (!_register) {
+            _register = new unsigned char[len];
+            _len = len;
+            memset(_register, 0, len);
+        } else if (len > _len) {
+            return -1;
+        }
+
+        if (!_next) {
+            _next = new unsigned char[_len];
+        }
+        memcpy(_next, block, _len);
+
+        rc = _cipher->decrypt(block, len);
+
+        if (rc != -1) {
+            // This might be optimizable
+            char *tb = (char *)block;
+            for (int i = 0; i < len; i++) {
+                tb[i] ^= ((char *)_register)[i];
+            }
+        }
+
+        void *temp;
+        temp = _next;
+        _next = _register;
+        _register = temp;
+
+        return rc;
+    }
+    return -1;
+}
+
+int CipherBlockChain::decrypt(void *block, int len)
+{
+    if (_useECBforReading) {
+        kDebug() << "decrypting using ECB!";
+        return decryptECB(block, len);
+    }
+
+    if (_cipher && !_writer) {
+        int rc = 0;
+
+        _reader |= 1;
+
+        initRegister();
+
+        if ((len % _len) >0) {
+            kDebug() << "Block length given for decrypt (" << len << ") is not a multiple of " << _len;
+            return -1;
+        }
+
+        char *elemBlock = static_cast<char*>(block);
+        for (int b = 0; b < len/_len; b++) {
+            if (_next == 0L) {
+                _next = new unsigned char[_len];
+            }
+            memcpy(_next, elemBlock, _len);
+
+            int bytesDecrypted = _cipher->decrypt(elemBlock, _len);
+
+            if (bytesDecrypted != -1) {
+                rc += bytesDecrypted;
+                // This might be optimizable
+                char *tb = (char *)elemBlock;
+                for (int i = 0; i < _len; i++) {
+                    *tb++ ^= ((char *)_register)[i];
+                }
+            }
+
+            void *temp;
+            temp = _next;
+            _next = _register;
+            _register = temp;
+
+            elemBlock += _len;
+        }
+
+        return rc;
+    }
+    return -1;
 }
 
-
-
-
Index: kdebase-runtime-4.3.5/kwalletd/backend/cbc.h
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/backend/cbc.h
+++ kdebase-runtime-4.3.5/kwalletd/backend/cbc.h
@@ -17,8 +17,6 @@
    Boston, MA 02110-1301, USA.
 */
 
-
-
 #ifndef __CBC__KO__H
 #define __CBC__KO__H
 
@@ -33,30 +31,35 @@
  *   calls to the other will fail in this instance.
  */
 
-class CipherBlockChain : public BlockCipher {
-	public:
-		CipherBlockChain(BlockCipher *cipher);
-		virtual ~CipherBlockChain();
+class CipherBlockChain : public BlockCipher
+{
+public:
+    CipherBlockChain(BlockCipher *cipher, bool useECBforReading =false);
+    virtual ~CipherBlockChain();
 
-		virtual bool setKey(void *key, int bitlength);
+    virtual bool setKey(void *key, int bitlength);
 
-		virtual int keyLen() const;
+    virtual int keyLen() const;
 
-		virtual bool variableKeyLen() const;
+    virtual bool variableKeyLen() const;
 
-		virtual bool readyToGo() const;
+    virtual bool readyToGo() const;
 
-		virtual int encrypt(void *block, int len);
+    virtual int encrypt(void *block, int len);
 
-		virtual int decrypt(void *block, int len);
+    virtual int decrypt(void *block, int len);
 
-	private: 
-		BlockCipher *_cipher;
-		void *_register;
-		void *_next;
-		int _len;
-		int _reader, _writer;
+private:
+    void initRegister();
+    int decryptECB(void *block, int len);
 
+    BlockCipher *_cipher;
+    void *_register;
+    void *_next;
+    int _len;
+    int _reader, _writer;
+    bool _useECBforReading;
 };
 
 #endif
+
Index: kdebase-runtime-4.3.5/kwalletd/tests/testbf.cpp
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/tests/testbf.cpp
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "blowfish.h"
+#include "cbc.h"
+
+int main()
+{
+    BlockCipher *bf;
+    char data[] = "This is a test.";
+    char expect[] = "\x3f\x3c\x2d\xae\x8c\x7\x84\xf2\xa7\x6d\x28\xbd\xd\xb\xb8\x79";
+    char key[] = "testkey";
+    unsigned long et[] = {0x11223344};
+
+    printf("%d:  0x11 == %d and 0x44 == %d\n", ((unsigned char *)et)[0],
+           0x11, 0x44);
+    bf = new BlowFish();
+//  bf = new CipherBlockChain(new BlowFish());
+
+    bf->setKey((void *)key, 7 * 8);
+
+    if (!bf->readyToGo()) {
+        printf("Error: not ready to go!\n");
+        return -1;
+    }
+
+    printf("About to encrypt...\n"); fflush(stdout);
+    if (-1 == bf->encrypt((void *)data, 16)) {
+        printf("Error: encrypt failed!\n");
+        return -1;
+    }
+
+    printf("Encryption done.  data[] is now: ");
+    for (int i = 0; i < 16; i++) {
+        printf("0x%x ", data[i] & 0xff);
+        if ((data[i] & 0xff) != (expect[i] & 0xff)) {
+            printf("Error.  This byte failed the comparison.  It should have been 0x%x.\n", expect[i] & 0xff);
+            break;
+        }
+    }
+    printf("\n");
+
+    delete bf;
+    bf = new BlowFish();
+//  bf = new CipherBlockChain(new BlowFish());
+    bf->setKey((void *)key, 7 * 8);
+
+    printf("About to decrypt...\n"); fflush(stdout);
+    if (-1 == bf->decrypt((void *)data, 16)) {
+        printf("Error: decrypt failed!\n");
+        return -1;
+    }
+    //bf->decrypt((void *)(data+8), 8);
+
+    printf("All done!  Result...  data[] = \"%s\"\n", data);
+    if (strcmp(data, "This is a test.")) {
+        printf("ERROR. Decryption failed.\n");
+        return -1;
+    }
+
+    delete bf;
+}
+
Index: kdebase-runtime-4.3.5/kwalletd/backend/kwalletbackend.h
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/backend/kwalletbackend.h
+++ kdebase-runtime-4.3.5/kwalletd/backend/kwalletbackend.h
@@ -28,7 +28,15 @@
 #include <QtCore/QStringList>
 #include <QtCore/QMap>
 #include "kwalletentry.h"
+#include "backendpersisthandler.h"
 
+#ifdef HAVE_QGPGME
+#include <gpgme++/key.h>
+#endif // HAVE_QGPGME
+
+#define PBKDF2_SHA512_KEYSIZE 56
+#define PBKDF2_SHA512_SALTSIZE 56
+#define PBKDF2_SHA512_ITERATIONS 50000
 
 namespace KWallet {
 
@@ -70,14 +78,23 @@ class KDE_EXPORT Backend {
 		// Open and unlock the wallet.
 		// If opening succeeds, the password's hash will be remembered.
 		// If opening fails, the password's hash will be cleared.
-		int open(const QByteArray& password);
+		int open(const QByteArray& password, WId w=0);
+
+#ifdef HAVE_QGPGME
+                int open(const GpgME::Key& key);
+#endif
+
+                // Open and unlock the wallet using a pre-hashed password.
+                // If opening succeeds, the password's hash will be remembered.
+                // If opening fails, the password's hash will be cleared.
+                int openPreHashed(const QByteArray &passwordHash);
 
 		// Close the wallet, losing any changes.
 		// if save is true, the wallet is saved prior to closing it.
 		int close(bool save = false);
 
 		// Write the wallet to disk
-		int sync();
+		int sync(WId w);
 
 		// Returns true if the current wallet is open.
 		bool isOpen() const;
@@ -143,6 +160,13 @@ class KDE_EXPORT Backend {
 
 		static QString openRCToString(int rc);
 
+                void setCipherType(BackendCipherType ct);
+                BackendCipherType cipherType() const { return _cipherType; }
+
+#ifdef HAVE_QGPGME
+                const GpgME::Key &gpgKey() const;
+#endif
+
 	private:
 		Q_DISABLE_COPY( Backend )
 		class BackendPrivate;
@@ -150,6 +174,7 @@ class KDE_EXPORT Backend {
 		QString _name;
 		QString _path;
 		bool _open;
+                bool _useNewHash;
 		QString _folder;
 		int _ref;
 		// Map Folder->Entries
@@ -159,6 +184,20 @@ class KDE_EXPORT Backend {
 		typedef QMap<MD5Digest, QList<MD5Digest> > HashMap;
 		HashMap _hashes;
 		QByteArray _passhash; // password hash used for saving the wallet
+                QByteArray _newPassHash; //Modern hash using KWALLET_HASH_PBKDF2_SHA512
+                BackendCipherType _cipherType; // the kind of encryption used for this wallet
+#ifdef HAVE_QGPGME
+        GpgME::Key      _gpgKey;
+#endif
+                friend class BlowfishPersistHandler;
+        friend class GpgPersistHandler;
+
+      // open the wallet with the password already set. This is
+      // called internally by both open and openPreHashed.
+      int openInternal(WId w=0);
+      void swapToNewHash();
+      QByteArray createAndSaveSalt(const QString &path) const;
+
 };
 
 }
Index: kdebase-runtime-4.3.5/kwalletd/backend/kwalletbackend.cc
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/backend/kwalletbackend.cc
+++ kdebase-runtime-4.3.5/kwalletd/backend/kwalletbackend.cc
@@ -28,6 +28,11 @@
 #include <kcodecs.h>
 #include <ksavefile.h>
 #include <kstandarddirs.h>
+#ifdef HAVE_QGPGME
+#include <gpgme++/key.h>
+#endif
+#include <gcrypt.h>
+#include <knotification.h>
 
 #include <QtCore/QFile>
 #include <QtCore/QFileInfo>
@@ -46,19 +51,11 @@
 #endif
 
 #define KWALLET_VERSION_MAJOR		0
-#define KWALLET_VERSION_MINOR		0
-
-#define KWALLET_CIPHER_BLOWFISH_CBC	0
-#define KWALLET_CIPHER_3DES_CBC		1 // unsupported
-
-#define KWALLET_HASH_SHA1		0
-#define KWALLET_HASH_MD5		1 // unsupported
-
+#define KWALLET_VERSION_MINOR		1
 
 using namespace KWallet;
 
 #define KWMAGIC "KWALLET\n\r\0\r\n"
-#define KWMAGIC_LEN 12
 
 class Backend::BackendPrivate
 {
@@ -69,18 +66,25 @@ static void initKWalletDir()
     KGlobal::dirs()->addResourceType("kwallet", 0, "share/apps/kwallet");
 }
 
-Backend::Backend(const QString& name, bool isPath) : d(0), _name(name), _ref(0) {
-	initKWalletDir();
-	if (isPath) {
-		_path = name;
-	} else {
-		_path = KGlobal::dirs()->saveLocation("kwallet") + _name + ".kwl";
-	}
+Backend::Backend(const QString& name, bool isPath)
+    : d(0)
+    , _name(name)
+    , _useNewHash(false)
+    , _ref(0)
+    , _cipherType(KWallet::BACKEND_CIPHER_UNKNOWN)
+{
+        initKWalletDir();
+        if (isPath) {
+                _path = name;
+        } else {
+                _path = KGlobal::dirs()->saveLocation("kwallet") + _name + ".kwl";
+        }
 
-	_open = false;
+        _open = false;
 }
 
 
+
 Backend::~Backend() {
 	if (_open) {
 		close();
@@ -88,90 +92,44 @@ Backend::~Backend() {
 	delete d;
 }
 
-static int getRandomBlock(QByteArray& randBlock) {
-
-#ifdef Q_OS_WIN //krazy:exclude=cpp
-
-	// Use windows crypto API to get randomness on win32
-	// HACK: this should be done using qca
-	HCRYPTPROV hProv;
-
-	if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
-	    CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) return -1; // couldn't get random data
-
-	if (!CryptGenRandom(hProv, static_cast<DWORD>(randBlock.size()),
-	    (BYTE*)randBlock.data())) {
-		return -3; // read error
-	}
-
-	// release the crypto context
-	CryptReleaseContext(hProv, 0);
-
-	return randBlock.size();
+void Backend::setCipherType(BackendCipherType ct)
+{
+    // changing cipher type on already initialed wallets is not permitted
+    assert(_cipherType == KWallet::BACKEND_CIPHER_UNKNOWN);
+    _cipherType = ct;
+}
 
+static int password2PBKDF2_SHA512(const QByteArray &password, QByteArray& hash, const QByteArray &salt)
+{
+    if (!gcry_check_version("1.5.0")) {
+        printf("libcrypt version is too old \n");
+        return GPG_ERR_USER_2;
+    }
+
+    gcry_error_t error;
+    bool static gcry_secmem_init = false;
+    if (!gcry_secmem_init) {
+        error = gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
+        if (error != 0) {
+            kWarning() << "Can't get secure memory:" << error;
+            return error;
+        }
+        gcry_secmem_init = true;
+    }
+
+    gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+
+#if (LIBGCRYPT_VERSION != 141)
+    error = gcry_kdf_derive(password.constData(), password.size(),
+                            GCRY_KDF_PBKDF2, GCRY_MD_SHA512,
+                            salt.data(), salt.size(),
+                            PBKDF2_SHA512_ITERATIONS, PBKDF2_SHA512_KEYSIZE, hash.data());
 #else
-
-	// First try /dev/urandom
-	if (QFile::exists("/dev/urandom")) {
-		QFile devrand("/dev/urandom");
-		if (devrand.open(QIODevice::ReadOnly)) {
-			int rc = devrand.read(randBlock.data(), randBlock.size());
-
-			if (rc != randBlock.size()) {
-				return -3;		// not enough data read
-			}
-
-			return 0;
-		}
-	}
-
-	// If that failed, try /dev/random
-	// FIXME: open in noblocking mode!
-	if (QFile::exists("/dev/random")) {
-		QFile devrand("/dev/random");
-		if (devrand.open(QIODevice::ReadOnly)) {
-			int rc = 0;
-			int cnt = 0;
-
-			do {
-				int rc2 = devrand.read(randBlock.data() + rc, randBlock.size());
-
-				if (rc2 < 0) {
-					return -3;	// read error
-				}
-
-				rc += rc2;
-				cnt++;
-				if (cnt > randBlock.size()) {
-					return -4;	// reading forever?!
-				}
-			} while(rc < randBlock.size());
-
-			return 0;
-		}
-	}
-
-	// EGD method
-	QString randFilename = QString::fromLocal8Bit(qgetenv("RANDFILE"));
-	if (!randFilename.isEmpty()) {
-		if (QFile::exists(randFilename)) {
-			QFile devrand(randFilename);
-			if (devrand.open(QIODevice::ReadOnly)) {
-				int rc = devrand.read(randBlock.data(), randBlock.size());
-				if (rc != randBlock.size()) {
-					return -3;      // not enough data read
-				}
-				return 0;
-			}
-		}
-	}
-
-	// Couldn't get any random data!!
-	return -1;
-
+    error = -1;
 #endif
-}
 
+    return error;
+}
 
 // this should be SHA-512 for release probably
 static int password2hash(const QByteArray& password, QByteArray& hash) {
@@ -308,15 +266,47 @@ QString Backend::openRCToString(int rc)
 	}
 }
 
+int Backend::open(const QByteArray& password, WId w) {
+        if (_open) {
+                return -255;  // already open
+        }
 
-int Backend::open(const QByteArray& password) {
+        setPassword(password);
+   return openInternal(w);
+}
 
-	if (_open) {
-		return -255;  // already open
-	}
-	
-	setPassword(password);
+#ifdef HAVE_QGPGME
+int Backend::open(const GpgME::Key& key)
+{
+    if (_open) {
+        return -255;  // already open
+    }
+    _gpgKey = key;
+    return openInternal();
+}
+#endif // HAVE_QGPGME
+
+int Backend::openPreHashed(const QByteArray &passwordHash)
+{
+   if (_open) {
+      return -255;  // already open
+   }
+
+   // check the password hash for correct size (currently fixed)
+   if (passwordHash.size() != 20 && passwordHash.size() != 40 &&
+           passwordHash.size() != 56) {
+      return -42; // unsupported encryption scheme
+   }
 
+   _passhash = passwordHash;
+   _newPassHash = passwordHash;
+   _useNewHash = true;//Only new hash is supported
+
+   return openInternal();
+}
+
+int Backend::openInternal(WId w)
+{
 	// No wallet existed.  Let's create it.
 	// Note: 60 bytes is presently the minimum size of a wallet file.
 	//       Anything smaller is junk and should be deleted.
@@ -327,8 +317,9 @@ int Backend::open(const QByteArray& pass
 		}
 		newfile.close();
 		_open = true;
-		sync();
-		return 1;          // new file opened, but OK
+                if (sync(w) != 0) {
+                    return -2;
+                }
 	}
 
 	QFile db(_path);
@@ -350,163 +341,56 @@ int Backend::open(const QByteArray& pass
 		return -4;         // unknown version
 	}
 
-	if (magicBuf[1] != KWALLET_VERSION_MINOR) {
-		return -4;	   // unknown version
-	}
-
-	if (magicBuf[2] != KWALLET_CIPHER_BLOWFISH_CBC) {
-		return -42;	   // unknown cipher
-	}
-
-	if (magicBuf[3] != KWALLET_HASH_SHA1) {
-		return -42;	   // unknown hash
-	}
-
-	_hashes.clear();
-	// Read in the hashes
-	QDataStream hds(&db);
-	quint32 n;
-	hds >> n;
-	if (n > 0xffff) { // sanity check
-		return -43;
-	}
-
-	for (size_t i = 0; i < n; ++i) {
-		KMD5::Digest d, d2; // judgment day
-		MD5Digest ba;
-		QMap<MD5Digest,QList<MD5Digest> >::iterator it;
-		quint32 fsz;
-		if (hds.atEnd()) return -43;
-		hds.readRawData(reinterpret_cast<char *>(d), 16);
-		hds >> fsz;
-		ba = MD5Digest(reinterpret_cast<char *>(d));
-		it = _hashes.insert(ba, QList<MD5Digest>());
-		for (size_t j = 0; j < fsz; ++j) {
-			hds.readRawData(reinterpret_cast<char *>(d2), 16);
-			ba = MD5Digest(reinterpret_cast<char *>(d2));
-			(*it).append(ba);
-		}
-	}
-
-	// Read in the rest of the file.
-	QByteArray encrypted = db.readAll();
-	assert(encrypted.size() < db.size());
-
-	BlowFish _bf;
-	CipherBlockChain bf(&_bf);
-	int blksz = bf.blockSize();
-	if ((encrypted.size() % blksz) != 0) {
-		return -5;	   // invalid file structure
-	}
-
-	bf.setKey((void *)_passhash.data(), _passhash.size()*8);
-
-	if (!encrypted.data()) {
-		_passhash.fill(0);
-		encrypted.fill(0);
-		return -7; // file structure error
-	}
-
-	int rc = bf.decrypt(encrypted.data(), encrypted.size());
-	if (rc < 0) {
-		_passhash.fill(0);
-		encrypted.fill(0);
-		return -6;	// decrypt error
-	}
-
-	const char *t = encrypted.data();
-
-	// strip the leading data
-	t += blksz;    // one block of random data
-
-	// strip the file size off
-	long fsize = 0;
-
-	fsize |= (long(*t) << 24) & 0xff000000;
-	t++;
-	fsize |= (long(*t) << 16) & 0x00ff0000;
-	t++;
-	fsize |= (long(*t) <<  8) & 0x0000ff00;
-	t++;
-	fsize |= long(*t) & 0x000000ff;
-	t++;
+        //0 has been the MINOR version until 4.13, from that point we use it to upgrade the hash
+        if (magicBuf[1] == 1) {
+        kDebug() << "Wallet new enough, using new hash";
+        swapToNewHash();
+        } else if (magicBuf[1] != 0){
+        kDebug() << "Wallet is old, sad panda :(";
+        return -4;  // unknown version
+    }
+
+        BackendPersistHandler *phandler = BackendPersistHandler::getPersistHandler(magicBuf);
+    if (0 == phandler){
+        return 42; // unknown cipher or hash
+    }
+    return phandler->read(this, db, w);
+}
 
-	if (fsize < 0 || fsize > long(encrypted.size()) - blksz - 4) {
-		//kDebug() << "fsize: " << fsize << " encrypted.size(): " << encrypted.size() << " blksz: " << blksz;
-		encrypted.fill(0);
-		return -9;         // file structure error.
-	}
+void Backend::swapToNewHash()
+{
+    //Runtime error happened and we can't use the new hash
+    if (!_useNewHash) {
+        kDebug() << "Runtime error on the new hash";
+        return;
+    }
+    _passhash.fill(0);//Making sure the old passhash is not around in memory
+    _passhash = _newPassHash;//Use the new hash, means the wallet is modern enough
+}
 
-	// compute the hash ourself
-	SHA1 sha;
-	sha.process(t, fsize);
-	const char *testhash = (const char *)sha.hash();
+QByteArray Backend::createAndSaveSalt(const QString& path) const
+{
+    QFile saltFile(path);
+    saltFile.remove();
 
-	// compare hashes
-	int sz = encrypted.size();
-	for (int i = 0; i < 20; i++) {
-		if (testhash[i] != encrypted[sz - 20 + i]) {
-			encrypted.fill(0);
-			sha.reset();
-			return -8;         // hash error.
-		}
-	}
+    if (!saltFile.open(QIODevice::WriteOnly)) {
+        return QByteArray();
+    }
 
-	sha.reset();
+    char *randomData = (char*) gcry_random_bytes(PBKDF2_SHA512_SALTSIZE, GCRY_STRONG_RANDOM);
+    QByteArray salt(randomData, PBKDF2_SHA512_SALTSIZE);
+    free(randomData);
 
-	// chop off the leading blksz+4 bytes
-	QByteArray tmpenc(encrypted.data()+blksz+4, fsize);
-	encrypted = tmpenc;
-	tmpenc.fill(0);
-
-	// Load the data structures up
-	QDataStream eStream(encrypted);
-
-	while (!eStream.atEnd()) {
-		QString folder;
-		quint32 n;
-
-		eStream >> folder;
-		eStream >> n;
-
-		// Force initialisation
-		_entries[folder].clear();
-
-		for (size_t i = 0; i < n; ++i) {
-			QString key;
-			KWallet::Wallet::EntryType et = KWallet::Wallet::Unknown;
-			Entry *e = new Entry;
-			eStream >> key;
-			qint32 x = 0; // necessary to read properly
-			eStream >> x;
-			et = static_cast<KWallet::Wallet::EntryType>(x);
-
-			switch (et) {
-			case KWallet::Wallet::Password:
-			case KWallet::Wallet::Stream:
-			case KWallet::Wallet::Map:
-			break;
-			default: // Unknown entry
-				delete e;
-				continue;
-			}
+    if (saltFile.write(salt) != PBKDF2_SHA512_SALTSIZE) {
+        return QByteArray();
+    }
 
-			QByteArray a;
-		 	eStream >> a;
-			e->setValue(a);
-			e->setType(et);
-			e->setKey(key);
-			_entries[folder][key] = e;
-		}
-	}
+    saltFile.close();
 
-	_open = true;
-	encrypted.fill(0);
-	return 0;
+    return salt;
 }
 
-
-int Backend::sync() {
+int Backend::sync(WId w) {
 	if (!_open) {
 		return -255;  // not open yet
 	}
@@ -526,160 +410,55 @@ int Backend::sync() {
 	// Write the version number
 	QByteArray version(4, 0);
 	version[0] = KWALLET_VERSION_MAJOR;
-	version[1] = KWALLET_VERSION_MINOR;
-	version[2] = KWALLET_CIPHER_BLOWFISH_CBC;
-	version[3] = KWALLET_HASH_SHA1;
-	if (sf.write(version, 4) != 4) {
-		sf.abort();
-		return -4; // write error
-	}
-
-	// Holds the hashes we write out
-	QByteArray hashes;
-	QDataStream hashStream(&hashes, QIODevice::WriteOnly);
-	KMD5 md5;
-	hashStream << static_cast<quint32>(_entries.count());
-
-	// Holds decrypted data prior to encryption
-	QByteArray decrypted;
-
-	// FIXME: we should estimate the amount of data we will write in each
-	// buffer and resize them approximately in order to avoid extra
-	// resizes.
-
-	// populate decrypted
-	QDataStream dStream(&decrypted, QIODevice::WriteOnly);
-	for (FolderMap::ConstIterator i = _entries.constBegin(); i != _entries.constEnd(); ++i) {
-		dStream << i.key();
-		dStream << static_cast<quint32>(i.value().count());
-
-		md5.reset();
-		md5.update(i.key().toUtf8());
-		hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
-		hashStream << static_cast<quint32>(i.value().count());
-
-		for (EntryMap::ConstIterator j = i.value().constBegin(); j != i.value().constEnd(); ++j) {
-			dStream << j.key();
-			dStream << static_cast<qint32>(j.value()->type());
-			dStream << j.value()->value();
-
-			md5.reset();
-			md5.update(j.key().toUtf8());
-			hashStream.writeRawData(reinterpret_cast<const char*>(&(md5.rawDigest()[0])), 16);
-		}
-	}
-
-	if (sf.write(hashes, hashes.size()) != hashes.size()) {
-		sf.abort();
-		return -4; // write error
-	}
-
-	// calculate the hash of the file
-	SHA1 sha;
-	BlowFish _bf;
-	CipherBlockChain bf(&_bf);
-
-	sha.process(decrypted.data(), decrypted.size());
-
-	// prepend and append the random data
-	QByteArray wholeFile;
-	long blksz = bf.blockSize();
-	long newsize = decrypted.size() +
-		       blksz            +    // encrypted block
-		       4                +    // file size
-		       20;      // size of the SHA hash
-
-	int delta = (blksz - (newsize % blksz));
-	newsize += delta;
-	wholeFile.resize(newsize);
-
-	QByteArray randBlock;
-	randBlock.resize(blksz+delta);
-	if (getRandomBlock(randBlock) < 0) {
-		sha.reset();
-		decrypted.fill(0);
-		sf.abort();
-		return -3;		// Fatal error: can't get random
-	}
-
-	for (int i = 0; i < blksz; i++) {
-		wholeFile[i] = randBlock[i];
-	}
-
-	for (int i = 0; i < 4; i++) {
-		wholeFile[(int)(i+blksz)] = (decrypted.size() >> 8*(3-i))&0xff;
-	}
-
-	for (int i = 0; i < decrypted.size(); i++) {
-		wholeFile[(int)(i+blksz+4)] = decrypted[i];
-	}
-
-	for (int i = 0; i < delta; i++) {
-		wholeFile[(int)(i+blksz+4+decrypted.size())] = randBlock[(int)(i+blksz)];
-	}
-
-	const char *hash = (const char *)sha.hash();
-	for (int i = 0; i < 20; i++) {
-		wholeFile[(int)(newsize - 20 + i)] = hash[i];
-	}
-
-	sha.reset();
-	decrypted.fill(0);
-
-	// encrypt the data
-	if (!bf.setKey(_passhash.data(), _passhash.size() * 8)) {
-		wholeFile.fill(0);
-		sf.abort();
-		return -2; // encrypt error
-	}
-
-	int rc = bf.encrypt(wholeFile.data(), wholeFile.size());
-	if (rc < 0) {
-		wholeFile.fill(0);
-		sf.abort();
-		return -2;	// encrypt error
-	}
-
-	// write the file
-	if (sf.write(wholeFile, wholeFile.size()) != wholeFile.size()) {
-		wholeFile.fill(0);
-		sf.abort();
-		return -4; // write error
-	}
-	if (!sf.finalize()) {
-		wholeFile.fill(0);
-		return -4; // write error
-	}
-
-	wholeFile.fill(0);
-
-	return 0;
+    if (_useNewHash) {
+        version[1] = KWALLET_VERSION_MINOR;
+        //Use the sync to update the hash to PBKDF2_SHA512
+        swapToNewHash();
+    } else {
+        version[1] = 0; //was KWALLET_VERSION_MINOR before the new hash
+    }
+
+
+    BackendPersistHandler *phandler = BackendPersistHandler::getPersistHandler(_cipherType);
+    if (0 == phandler) {
+        return -4; // write error
+    }
+    int rc = phandler->write(this, sf, version, w);
+    if (rc<0) {
+        // Oops! wallet file sync filed! Display a notification about that
+        // TODO: change kwalletd status flags, when status flags will be implemented
+        KNotification *notification = new KNotification( "syncFailed" );
+        notification->setText( i18n("Failed to sync wallet <b>%1</b> to disk. Error codes are:\nRC <b>%2</b>\nSF <b>%3</b>. Please file a BUG report using this information to bugs.kde.org").arg(_name).arg(rc).arg(sf.errorString()) );
+        notification->sendEvent();
+    }
+    return rc;
 }
 
 
 int Backend::close(bool save) {
-	// save if requested
-	if (save) {
-		int rc = sync();
-		if (rc != 0) {
-			return rc;
-		}
-	}
-	
-	// do the actual close
-	for (FolderMap::ConstIterator i = _entries.constBegin(); i != _entries.constEnd(); ++i) {
-		for (EntryMap::ConstIterator j = i.value().constBegin(); j != i.value().constEnd(); ++j) {
-			delete j.value();
-		}
-	}
-	_entries.clear();
-	
-	// empty the password hash
-	_passhash.fill(0);
+        // save if requested
+        if (save) {
+                int rc = sync(0);
+                if (rc != 0) {
+                        return rc;
+                }
+        }
+
+        // do the actual close
+        for (FolderMap::ConstIterator i = _entries.constBegin(); i != _entries.constEnd(); ++i) {
+                for (EntryMap::ConstIterator j = i.value().constBegin(); j != i.value().constEnd(); ++j) {
+                        delete j.value();
+                }
+        }
+        _entries.clear();
+
+        // empty the password hash
+        _passhash.fill(0);
+    _newPassHash.fill(0);
 
-	_open = false;
-	
-	return 0;
+        _open = false;
+
+        return 0;
 }
 
 const QString& Backend::walletName() const {
@@ -876,9 +655,38 @@ bool Backend::entryDoesNotExist(const QS
 }
 
 void Backend::setPassword(const QByteArray &password) {
-	_passhash.fill(0); // empty just in case
-	BlowFish _bf;
-	CipherBlockChain bf(&_bf);
-	_passhash.resize(bf.keyLen()/8);
-	password2hash(password, _passhash);
+        _passhash.fill(0); // empty just in case
+        BlowFish _bf;
+        CipherBlockChain bf(&_bf);
+        _passhash.resize(bf.keyLen()/8);
+    _newPassHash.resize(bf.keyLen()/8);
+    _newPassHash.fill(0);
+
+        password2hash(password, _passhash);
+
+    QByteArray salt;
+    QFile saltFile(KGlobal::dirs()->saveLocation("kwallet") + _name + ".salt");
+    if (!saltFile.exists() || saltFile.size() == 0) {
+        salt = createAndSaveSalt(saltFile.fileName());
+    } else {
+        if (!saltFile.open(QIODevice::ReadOnly)) {
+            salt = createAndSaveSalt(saltFile.fileName());
+        } else {
+            salt = saltFile.readAll();
+        }
+    }
+
+#if (LIBGCRYPT_VERSION != 141)
+    if (!salt.isEmpty() && password2PBKDF2_SHA512(password, _newPassHash,  salt) == 0) {
+        kDebug() << "Setting useNewHash to true";
+        _useNewHash = true;
+    }
+#endif
 }
+
+#ifdef HAVE_QGPGME
+const GpgME::Key &Backend::gpgKey() const {
+    return _gpgKey;
+}
+#endif
+
Index: kdebase-runtime-4.3.5/kwalletd/CMakeLists.txt
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/CMakeLists.txt
+++ kdebase-runtime-4.3.5/kwalletd/CMakeLists.txt
@@ -1,11 +1,26 @@
 project(kwalletd)
 
+########### find needed packages ######
+find_package(Gpgme)  # Called by FindQGpgme, but since we call some gpgme
+                     # functions ourselves we need to link against it directly.
+find_package(QGpgme) # provided by kdepimlibs
+
+if (GPGME_FOUND AND QGPGME_FOUND)
+    add_definitions(-DHAVE_QGPGME)
+    add_definitions(-DLIBGCRYPT_VERSION=`echo ${LIBGCRYPT_VERSION} | tr -d .`)
+    include_directories(${GPGME_INCLUDES} ${QGPGME_INCLUDE_DIR})
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}")
+endif(GPGME_FOUND AND QGPGME_FOUND)
+
+########### build backends #########
 add_subdirectory(backend)
 
 ########### kwalletd ###############
 
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backend)
 
+add_definitions(-DKDE_DEFAULT_DEBUG_AREA=285)
+
 set(kwalletd_KDEINIT_SRCS
    main.cpp
    kbetterthankdialog.cpp
@@ -25,6 +40,19 @@ kde4_add_ui_files(kwalletd_KDEINIT_SRCS
    kwalletwizardpagepassword.ui
 )
 
+if (GPGME_FOUND AND QGPGME_FOUND)
+    set(kwalletd_KDEINIT_SRCS
+        ${kwalletd_KDEINIT_SRCS}
+        knewwalletdialog.cpp
+    )
+    kde4_add_ui_files(kwalletd_KDEINIT_SRCS
+        kwalletwizardpagepasswordgpg.ui
+        kwalletwizardpagegpgkey.ui
+        knewwalletdialogintro.ui
+        knewwalletdialoggpg.ui
+    )
+endif(GPGME_FOUND AND QGPGME_FOUND)
+
 MESSAGE( "KDE4_DBUS_INTERFACES_DIR = ${KDE4_DBUS_INTERFACES_DIR}" )
 
 find_file(kwallet_xml org.kde.KWallet.xml HINTS ${KDE4_DBUS_INTERFACES_DIR} )
@@ -35,6 +63,10 @@ kde4_add_kdeinit_executable( kwalletd NO
 
 # uses kio for KDirWatch
 target_link_libraries(kdeinit_kwalletd  ${KDE4_KIO_LIBS} kwalletbackend )
+if (GPGME_FOUND AND QGPGME_FOUND)
+    target_link_libraries(kdeinit_kwalletd ${QGPGME_LIBRARIES} )
+endif(GPGME_FOUND AND QGPGME_FOUND)
+
 install(TARGETS kdeinit_kwalletd  ${INSTALL_TARGETS_DEFAULT_ARGS})
 
 target_link_libraries(kwalletd kdeinit_kwalletd)
Index: kdebase-runtime-4.3.5/kwalletd/backend/CMakeLists.txt
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/backend/CMakeLists.txt
+++ kdebase-runtime-4.3.5/kwalletd/backend/CMakeLists.txt
@@ -14,16 +14,20 @@ set(kwalletbackend_LIB_SRCS
    sha1.cc
    kwalletentry.cc
    kwalletbackend.cc
+   backendpersisthandler.cpp
 )
 
 kde4_add_library(kwalletbackend SHARED ${kwalletbackend_LIB_SRCS})
 
-target_link_libraries(kwalletbackend ${KDE4_KDEUI_LIBS} )
+target_link_libraries(kwalletbackend ${KDE4_KDEUI_LIBS} ${LIBGCRYPT_LIBRARIES})
+if(QGPGME_FOUND)
+target_link_libraries(kwalletbackend ${QGPGME_LIBRARIES} )
+endif(QGPGME_FOUND)
 
 # link with advapi32 on windows
-if(WIN32)
+if(WIN32 AND NOT WINCE)
    target_link_libraries(kwalletbackend advapi32)
-endif(WIN32)
+endif(WIN32 AND NOT WINCE)
 
 set_target_properties(kwalletbackend PROPERTIES VERSION ${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION} )
 install(TARGETS kwalletbackend ${INSTALL_TARGETS_DEFAULT_ARGS})
Index: kdebase-runtime-4.3.5/CMakeLists.txt
===================================================================
--- kdebase-runtime-4.3.5.orig/CMakeLists.txt
+++ kdebase-runtime-4.3.5/CMakeLists.txt
@@ -16,6 +16,8 @@ include(MacroLibrary)
 include(CheckFunctionExists)
 include(CheckIncludeFiles)
 
+find_package(LibGcrypt 1.5.0 REQUIRED)
+
 set(SOPRANO_MIN_VERSION "2.3.0")
 macro_optional_find_package(Soprano)
 macro_optional_find_package(Nepomuk)
Index: kdebase-runtime-4.3.5/cmake/modules/FindLibGcrypt.cmake
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/cmake/modules/FindLibGcrypt.cmake
@@ -0,0 +1,79 @@
+#.rst
+# FindLibGcrypt
+# -------------
+#
+# Finds the Libgcrypt library.
+#
+# This will define the following variables:
+#
+# ``LIBGCRYPT_FOUND``
+#     True if the requested version of gcrypt was found
+# ``LIBGCRYPT_VERSION``
+#     The version of gcrypt that was found
+# ``LIBGCRYPT_INCLUDE_DIRS``
+#     The gcrypt include directories
+# ``LIBGCRYPT_LIBRARIES``
+#     The linker libraries needed to use the gcrypt library
+
+# Copyright 2014 Nicolás Alvarez <nicolas.alvarez@gmail.com>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+#    derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+find_program(LIBGCRYPTCONFIG_SCRIPT NAMES libgcrypt-config)
+if(LIBGCRYPTCONFIG_SCRIPT)
+    execute_process(COMMAND "${LIBGCRYPTCONFIG_SCRIPT}" --prefix OUTPUT_VARIABLE PREFIX)
+    set(LIBGCRYPT_LIB_HINT "${PREFIX}/lib")
+    set(LIBGCRYPT_INCLUDE_HINT "${PREFIX}/include")
+endif()
+
+find_library(LIBGCRYPT_LIBRARY
+    NAMES gcrypt
+    HINTS ${LIBGCRYPT_LIB_HINT}
+)
+find_path(LIBGCRYPT_INCLUDE_DIR
+    NAMES gcrypt.h
+    HINTS ${LIBGCRYPT_INCLUDE_HINT}
+)
+
+if(LIBGCRYPT_INCLUDE_DIR)
+    file(STRINGS ${LIBGCRYPT_INCLUDE_DIR}/gcrypt.h GCRYPT_H REGEX "^#define GCRYPT_VERSION ")
+    string(REGEX REPLACE "^#define GCRYPT_VERSION \"(.*)\".*$" "\\1" LIBGCRYPT_VERSION "${GCRYPT_H}")
+endif()
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(LibGcrypt LIBGCRYPT_LIBRARY LIBGCRYPT_INCLUDE_DIR)
+#VERSION_VAR LIBGCRYPT_VERSION REQUIRED_VARS LIBGCRYPT_LIBRARY LIBGCRYPT_INCLUDE_DIR)
+if(LIBGCRYPT_FOUND)
+    set(LIBGCRYPT_LIBRARIES ${LIBGCRYPT_LIBRARY})
+    set(LIBGCRYPT_INCLUDE_DIRS ${LIBGCRYPT_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(LIBGCRYPT_LIBRARY LIBGCRYPT_INCLUDE_DIR)
+
+include(FeatureSummary)
+#set_package_properties(LibGcrypt PROPERTIES
+#    DESCRIPTION "A general purpose cryptographic library based on the code from GnuPG."
+#    URL "http://www.gnu.org/software/libgcrypt/"
+#)
Index: kdebase-runtime-4.3.5/kwalletd/kwalletd.cpp
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/kwalletd.cpp
+++ kdebase-runtime-4.3.5/kwalletd/kwalletd.cpp
@@ -27,6 +27,10 @@
 #include "kbetterthankdialog.h"
 #include "kwalletwizard.h"
 
+#ifdef HAVE_QGPGME
+#include "knewwalletdialog.h"
+#endif
+
 #include <kuniqueapplication.h>
 #include <ktoolinvocation.h>
 #include <kconfig.h>
@@ -44,6 +48,9 @@
 #include <kpluginfactory.h>
 #include <kpluginloader.h>
 #include <KNotification>
+#ifdef HAVE_QGPGME
+#include <gpgme++/key.h>
+#endif
 
 #include <QtCore/QDir>
 #include <QtGui/QTextDocument> // Qt::escape
@@ -97,7 +104,10 @@ class KWalletTransaction {
 int KWalletTransaction::nextTransactionId = 0;
 
 KWalletD::KWalletD()
- : QObject(0), _failed(0), _syncTime(5000), _curtrans(0) {
+ : QObject(0), _failed(0), _syncTime(5000), _curtrans(0), _useGpg(false) {
+#ifdef HAVE_QGPGME
+     _useGpg = true;
+#endif
 
 	srand(time(0));
 	_showingFailureNotify = false;
@@ -374,10 +384,22 @@ int KWalletD::doTransactionOpen(const QS
 
 			// Create the wallet
 			KWallet::Backend *b = new KWallet::Backend(KWallet::Wallet::LocalWallet());
+#ifdef HAVE_QGPGME
+	            if (wiz->field("useBlowfish").toBool()) {
+        	        b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
+#endif
+
 			QString pass = wiz->field("pass1").toString();
 			QByteArray p(pass.toUtf8(), pass.length());
 			b->open(p);
 			p.fill(0);
+#ifdef HAVE_QGPGME
+            } else {
+                assert(wiz->field("useGpg").toBool());
+                b->setCipherType(KWallet::BACKEND_CIPHER_GPG);
+                b->open(wiz->gpgKey());
+            }
+#endif
 			b->createFolder(KWallet::Wallet::PasswordFolder());
 			b->createFolder(KWallet::Wallet::FormDataFolder());
 			b->close(true);
@@ -426,7 +448,20 @@ int KWalletD::internalOpen(const QString
 		QString password;
 		bool emptyPass = false;
 		if ((isPath && QFile::exists(wallet)) || (!isPath && KWallet::Backend::exists(wallet))) {
-			int pwless = b->open(QByteArray());
+            // this open attempt will set wallet type from the file header, even if password is needed
+			int pwless = b->open(QByteArray(), w);
+#ifdef HAVE_QGPGME
+            assert(b->cipherType() != KWallet::BACKEND_CIPHER_UNKNOWN);
+            if (b->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
+                // GPG based wallets do not prompt for password here. Instead, GPG should already have popped pinentry utility for wallet decryption
+                if (!b->isOpen()){
+                    // for some reason, GPG operation failed
+                    delete b;
+                    return -1;
+                }
+                emptyPass = true;
+            } else {
+#endif
 			if (0 != pwless || !b->isOpen()) {
 				if (pwless == 0) {
 					// release, start anew
@@ -477,6 +512,7 @@ int KWalletD::internalOpen(const QString
 						int rc = b->open(password.toUtf8());
 						if (!b->isOpen()) {
 							kpd->setPrompt(i18n("<qt>Error opening the wallet '<b>%1</b>'. Please try again.<br />(Error code %2: %3)</qt>", Qt::escape(wallet), rc, KWallet::Backend::openRCToString(rc)));
+                                kpd->setPassword("");
 						}
 					} else {
 						break;
@@ -486,7 +522,34 @@ int KWalletD::internalOpen(const QString
 			} else {
 				emptyPass = true;
 			}
+#ifdef HAVE_QGPGME
+            }
+#endif
 		} else {
+            brandNew = true;
+#ifdef HAVE_QGPGME
+            // prompt the user for the new wallet format here
+            KWallet::BackendCipherType newWalletType = KWallet::BACKEND_CIPHER_UNKNOWN;
+
+            boost::shared_ptr<KWallet::KNewWalletDialog> newWalletDlg( new KWallet::KNewWalletDialog(appid, wallet, QWidget::find(w)));
+            GpgME::Key gpgKey;
+            setupDialog( newWalletDlg.get(), (WId)w, appid, true );
+            if (newWalletDlg->exec() == QDialog::Accepted) {
+                newWalletType = newWalletDlg->isBlowfish() ? KWallet::BACKEND_CIPHER_BLOWFISH : KWallet::BACKEND_CIPHER_GPG;
+                gpgKey = newWalletDlg->gpgKey();
+            } else {
+                // user cancelled the dialog box
+                delete b;
+                return -1;
+            }
+
+            if (newWalletType == KWallet::BACKEND_CIPHER_GPG) {
+                b->setCipherType(newWalletType);
+                b->open(gpgKey);
+            } else if (newWalletType == KWallet::BACKEND_CIPHER_BLOWFISH) {
+#endif // HAVE_QGPGME
+            b->setCipherType(KWallet::BACKEND_CIPHER_BLOWFISH);
+
 			KNewPasswordDialog *kpd = new KNewPasswordDialog();
 			if (wallet == KWallet::Wallet::LocalWallet() ||
 						 wallet == KWallet::Wallet::NetworkWallet())
@@ -521,16 +584,18 @@ int KWalletD::internalOpen(const QString
 				}
 			}
 			delete kpd;
+#ifdef HAVE_QGPGME
+            }
+#endif
 		}
 
+                if ((b->cipherType() == KWallet::BACKEND_CIPHER_BLOWFISH) &&
+            !emptyPass && (password.isNull() || !b->isOpen())) {
+                        delete b;
+                        return -1;
+                }
 
-
-		if (!emptyPass && (password.isNull() || !b->isOpen())) {
-			delete b;
-			return -1;
-		}
-
-		if (emptyPass && _openPrompt && !isAuthorizedApp(appid, wallet, w)) {
+		if (emptyPass && !isAuthorizedApp(appid, wallet, w)) {
 			delete b;
 			return -1;
 		}
@@ -698,6 +763,13 @@ void KWalletD::doTransactionChangePasswo
 
 	assert(w);
 
+#ifdef HAVE_QGPGME
+    if (w->cipherType() == KWallet::BACKEND_CIPHER_GPG) {
+        QString keyID = w->gpgKey().shortKeyID();
+        assert(!keyID.isNull());
+        KMessageBox::errorWId((WId)wId, i18n("<qt>The <b>%1</b> wallet is encrypted using GPG key <b>%2</b>. Please use <b>GPG</b> tools (such as <b>kleopatra</b>) to change the passphrase associated to that key.</qt>", Qt::escape(wallet), keyID));
+    } else {
+#endif
 	KNewPasswordDialog *kpd = new KNewPasswordDialog();
 	kpd->setPrompt(i18n("<qt>Please choose a new password for the wallet '<b>%1</b>'.</qt>", Qt::escape(wallet)));
 	kpd->setCaption(i18n("KDE Wallet Service"));
@@ -722,6 +794,9 @@ void KWalletD::doTransactionChangePasswo
 	}
 
 	delete kpd;
+#ifdef HAVE_QGPGME
+    }
+#endif
 
 	if (reclose) {
 		internalClose(w, handle, true);
@@ -828,14 +903,14 @@ void KWalletD::sync(int handle, const QS
 	// get the wallet and check if we have a password for it (safety measure)
 	if ((b = getWallet(appid, handle))) {
 		QString wallet = b->walletName();
-		b->sync();
+		b->sync(0);
 	}
 }
 
 void KWalletD::timedOutSync(int handle) {
 	_syncTimers.removeTimer(handle);
 	if (_wallets.contains(handle) && _wallets[handle]) {
-		_wallets[handle]->sync();
+		_wallets[handle]->sync(0);
 	}
 }
 
Index: kdebase-runtime-4.3.5/kwalletd/kwalletd.h
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/kwalletd.h
+++ kdebase-runtime-4.3.5/kwalletd/kwalletd.h
@@ -233,6 +233,8 @@ class KWalletD : public QObject, protect
 
 		// sessions
 		KWalletSessionStore _sessions;
+
+        bool _useGpg;
 };
 
 
Index: kdebase-runtime-4.3.5/kwalletd/kwalletwizard.cpp
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/kwalletwizard.cpp
+++ kdebase-runtime-4.3.5/kwalletd/kwalletwizard.cpp
@@ -23,11 +23,25 @@
 #include "ui_kwalletwizardpageintro.h"
 #include "ui_kwalletwizardpageoptions.h"
 #include "ui_kwalletwizardpagepassword.h"
+#ifdef HAVE_QGPGME
+#include "ui_kwalletwizardpagepasswordgpg.h"
+#include "ui_kwalletwizardpagegpgkey.h"
+#endif
 
 #include <QtGui/QButtonGroup>
 
 #include <klocale.h>
 
+#ifdef HAVE_QGPGME
+#include <QComboBox>
+#include <gpgme++/context.h>
+#include <gpgme++/key.h>
+#include <gpgme++/keylistresult.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <gpgme.h>
+#endif
+
 class PageIntro : public QWizardPage
 {
 public:
@@ -63,6 +77,11 @@ public:
         registerField("useWallet", ui._useWallet);
         registerField("pass1", ui._pass1);
         registerField("pass2", ui._pass2);
+#ifdef HAVE_QGPGME
+        registerField("useGPG", ui._radioGpg);
+        registerField("useBlowfish", ui._radioBlowfish);
+        connect(ui._radioBlowfish, SIGNAL(toggled(bool)), parent, SLOT(passwordPageUpdate()));
+#endif
 
         connect(ui._useWallet, SIGNAL(clicked()), parent, SLOT(passwordPageUpdate()));
         connect(ui._pass1, SIGNAL(textChanged(QString)), parent, SLOT(passwordPageUpdate()));
@@ -71,7 +90,20 @@ public:
 
     virtual int nextId() const
     {
+#ifdef HAVE_QGPGME
+        int nextId = -1;
+        if (field("useWallet").toBool()) {
+            if (field("useBlowfish").toBool()) {
+                nextId = static_cast<KWalletWizard*>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId; // same as non QGPGME case
+            } else {
+                nextId = KWalletWizard::PageGpgKeyId;
+            }
+        }
+
+        return nextId;
+#else
         return static_cast<KWalletWizard*>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId;
+#endif
     }
 
     void setMatchLabelText(const QString &text)
@@ -80,9 +112,96 @@ public:
     }
 
 private:
+#ifdef HAVE_QGPGME
+    Ui::KWalletWizardPagePasswordGpg ui;
+#else
     Ui::KWalletWizardPagePassword ui;
+#endif
 };
 
+#ifdef HAVE_QGPGME
+typedef std::vector< GpgME::Key > KeysVector;
+Q_DECLARE_METATYPE(GpgME::Key)
+
+struct AddKeyToCombo {
+    QComboBox *_list;
+    AddKeyToCombo(QComboBox *list) : _list(list) {}
+    void operator()( const GpgME::Key &k) {
+        QString text = QString("%1 (%2)").arg(k.shortKeyID()).arg(k.userID(0).email());
+        QVariant varKey;
+        varKey.setValue(k);
+        _list->addItem(text, varKey);
+    }
+};
+
+class PageGpgKey : public QWizardPage
+{
+public:
+    PageGpgKey(QWidget* parent)
+        : QWizardPage(parent)
+        , userHasGpgKeys(false)
+    {
+        ui.setupUi(this);
+
+        registerField("gpgKey", ui._gpgKey);
+
+        KeysVector keys;
+        GpgME::initializeLibrary();
+        GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
+        if (err){
+            kDebug() << "OpenPGP not supported on your system!";
+            KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
+        } else {
+            boost::shared_ptr< GpgME::Context > ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+            if (0 == ctx) {
+                KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
+            } else {
+
+            ctx->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL);
+            int row =0;
+            err = ctx->startKeyListing();
+            while (!err) {
+                GpgME::Key k = ctx->nextKey(err);
+                if (err)
+                    break;
+                if (!k.isInvalid() && k.canEncrypt() && (k.ownerTrust() == GpgME::Key::Ultimate)) {
+                    keys.push_back(k);
+                }
+            }
+            ctx->endKeyListing();
+            }
+        }
+        std::for_each(keys.begin(), keys.end(), AddKeyToCombo(ui._gpgKey));
+
+        userHasGpgKeys = keys.size() >0;
+        if (userHasGpgKeys) {
+            ui.stackedWidget->setCurrentWidget(ui._pageWhenHasKeys);
+        } else {
+            ui.stackedWidget->setCurrentWidget(ui._pageNoKeys);
+            setFinalPage(true);
+        }
+        emit completeChanged();
+    }
+
+    virtual int nextId() const {
+        return static_cast<KWalletWizard*>(wizard())->wizardType() == KWalletWizard::Basic ? -1 : KWalletWizard::PageOptionsId;
+    }
+
+    virtual bool isComplete() const {
+        return userHasGpgKeys;
+    }
+
+    bool hasGpgKeys() const { return userHasGpgKeys; }
+
+    GpgME::Key gpgKey() const {
+        QVariant varKey = ui._gpgKey->itemData(field("gpgKey").toInt());
+        return varKey.value< GpgME::Key >();
+    }
+private:
+    Ui::KWalletWizardPageGpgKey ui;
+    bool userHasGpgKeys;
+};
+#endif
 
 class PageOptions : public QWizardPage
 {
@@ -126,14 +245,25 @@ KWalletWizard::KWalletWizard( QWidget *p
     setPage(PageIntroId, m_pageIntro);
     m_pagePasswd = new PagePassword(this);
     setPage(PagePasswordId, m_pagePasswd);
+#ifdef HAVE_QGPGME
+    m_pageGpgKey = new PageGpgKey(this);
+    setPage(PageGpgKeyId, m_pageGpgKey);
+#endif
     setPage(PageOptionsId, new PageOptions(this));
     setPage(PageExplanationId, new PageExplanation(this));
+
+    resize(500, 420);
 }
 
 void KWalletWizard::passwordPageUpdate()
 {
     bool complete = true;
     if (field("useWallet").toBool()) {
+#ifdef HAVE_QGPGME
+        if (field("useBlowfish").toBool()) {
+            m_pagePasswd->setFinalPage(wizardType() == Basic);
+            button(NextButton)->setVisible(wizardType() != Basic);
+#endif
         if (field("pass1").toString() == field("pass2").toString()) {
             if (field("pass1").toString().isEmpty()) {
                 m_pagePasswd->setMatchLabelText(i18n("<qt>Password is empty.  <b>(WARNING: Insecure)</b></qt>"));
@@ -144,6 +274,13 @@ void KWalletWizard::passwordPageUpdate()
             m_pagePasswd->setMatchLabelText(i18n("Passwords do not match."));
             complete = false;
         }
+#ifdef HAVE_QGPGME
+        } else {
+            m_pagePasswd->setFinalPage(false);
+            button(NextButton)->setEnabled(true);
+            return;
+        }
+#endif
     } else {
         m_pagePasswd->setMatchLabelText(QString());
     }
@@ -168,3 +305,9 @@ void KWalletWizard::initializePage(int i
     }
 }
 
+#ifdef HAVE_QGPGME
+GpgME::Key KWalletWizard::gpgKey() const {
+    return m_pageGpgKey->gpgKey();
+}
+#endif
+
Index: kdebase-runtime-4.3.5/kwalletd/kwalletwizard.h
===================================================================
--- kdebase-runtime-4.3.5.orig/kwalletd/kwalletwizard.h
+++ kdebase-runtime-4.3.5/kwalletd/kwalletwizard.h
@@ -20,7 +20,11 @@
 #define KWALLETWIZARD_H
 
 #include <QtGui/QWizard>
+#ifdef HAVE_QGPGME
+#include <gpgme++/key.h>
+#endif
 
+class PageGpgKey;
 class PageIntro;
 class PagePassword;
 
@@ -37,13 +41,20 @@ class KWalletWizard : public QWizard
 
         static const int PageIntroId = 0;
         static const int PagePasswordId = 1;
-        static const int PageOptionsId = 2;
-        static const int PageExplanationId = 3;
+#ifdef HAVE_QGPGME
+        static const int PageGpgKeyId =2;
+#endif
+        static const int PageOptionsId = 3;
+        static const int PageExplanationId = 4;
 
     KWalletWizard( QWidget *parent = 0 );
 
         WizardType wizardType() const;
 
+#ifdef HAVE_QGPGME
+        GpgME::Key gpgKey() const;
+#endif // HAVE_QGPGME
+
     protected:
         virtual void initializePage(int id);
 
@@ -53,6 +64,9 @@ class KWalletWizard : public QWizard
     private:
         PageIntro *m_pageIntro;
         PagePassword *m_pagePasswd;
+#ifdef HAVE_QGPGME
+        PageGpgKey *m_pageGpgKey;
+#endif
 };
 
 #endif
Index: kdebase-runtime-4.3.5/kwalletd/knewwalletdialoggpg.ui
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/knewwalletdialoggpg.ui
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KNewWalletDialogGpg</class>
+ <widget class="QWidget" name="KNewWalletDialogGpg">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Please select the signing key from the list below:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;NOTE:&lt;/span&gt; this list shows only &amp;quot;ultimate-level&amp;quot; trusted keys&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QTableWidget" name="listCertificates">
+     <property name="showDropIndicator" stdset="0">
+      <bool>false</bool>
+     </property>
+     <property name="dragDropOverwriteMode">
+      <bool>false</bool>
+     </property>
+     <property name="selectionBehavior">
+      <enum>QAbstractItemView::SelectRows</enum>
+     </property>
+     <property name="showGrid">
+      <bool>false</bool>
+     </property>
+     <property name="columnCount">
+      <number>3</number>
+     </property>
+     <attribute name="horizontalHeaderCascadingSectionResizes">
+      <bool>true</bool>
+     </attribute>
+     <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+      <bool>true</bool>
+     </attribute>
+     <attribute name="verticalHeaderVisible">
+      <bool>false</bool>
+     </attribute>
+     <attribute name="verticalHeaderHighlightSections">
+      <bool>false</bool>
+     </attribute>
+     <column>
+      <property name="text">
+       <string>Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>E-Mail</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Key-ID</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>listCertificates</sender>
+   <signal>itemSelectionChanged()</signal>
+   <receiver>KNewWalletDialogGpg</receiver>
+   <slot>onItemSelectionChanged()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>48</x>
+     <y>89</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>0</x>
+     <y>81</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <slots>
+  <slot>onItemSelectionChanged()</slot>
+ </slots>
+</ui>
+
Index: kdebase-runtime-4.3.5/kwalletd/knewwalletdialogintro.ui
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/knewwalletdialogintro.ui
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KNewWalletDialogIntro</class>
+ <widget class="QWidget" name="KNewWalletDialogIntro">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>341</width>
+    <height>190</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="KTitleWidget" name="ktitlewidget">
+     <property name="comment">
+      <string>The KDE Wallet System</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="labelIntro">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The application '&lt;span style=&quot; font-weight:600;&quot;&gt;%1&lt;/span&gt;' has requested to open the KDE wallet. This is used to store sensitive data in a secure fashion. Please choose the new wallet's type below or click cancel to deny the application's request.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignVCenter</set>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+     <property name="margin">
+      <number>12</number>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QRadioButton" name="radioBlowfish">
+         <property name="text">
+          <string>Classic, blowfish encrypted file</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QRadioButton" name="radioGpg">
+         <property name="text">
+          <string>Use GPG encryption, for better protection</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer_2">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KTitleWidget</class>
+   <extends>QWidget</extends>
+   <header>ktitlewidget.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>radioBlowfish</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>KNewWalletDialogIntro</receiver>
+   <slot>onBlowfishToggled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>31</x>
+     <y>144</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>2</x>
+     <y>138</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <slots>
+  <slot>onBlowfishToggled(bool)</slot>
+ </slots>
+</ui>
+
Index: kdebase-runtime-4.3.5/kwalletd/kwalletwizardpagegpgkey.ui
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/kwalletwizardpagegpgkey.ui
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KWalletWizardPageGpgKey</class>
+ <widget class="QWidget" name="KWalletWizardPageGpgKey">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>436</width>
+    <height>309</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <item>
+    <widget class="QStackedWidget" name="stackedWidget">
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="_pageWhenHasKeys">
+      <layout class="QVBoxLayout" name="verticalLayout_2">
+       <item>
+        <widget class="QLabel" name="label_3">
+         <property name="text">
+          <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The GPG-based wallet use a GPG encryption key to securely encrypt data on disk. The key must be available when decrypting is needed or your wallet will not be accessible. For example, if you choose a SmartCard-based encryption key, the GPG system will prompt you to enter it and its associated PIN when attempting to open the wallet. &lt;b&gt;NOTE:&lt;/b&gt; only &amp;quot;ultimate-level&amp;quot; trusted keys are shown in this list.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QLabel" name="label">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
+           <property name="text">
+            <string>Select encryption GPG key:</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="_gpgKey">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>173</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="_pageNoKeys">
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QLabel" name="label_2">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="text">
+          <string>Unable to locate at least one &lt;b&gt;encrypting GPG key&lt;/b&gt;. KDE Wallet needs such &lt;b&gt;encrypting key&lt;/b&gt; to securely store passwords or other sensitive data on disk. If you still want to setup a GPG-based wallet, then cancel this wizard, set-up an &lt;b&gt;encrypting GPG key&lt;/b&gt;, then retry this assistant. Otherwise, you may still click back, then choose a classic, blowfish encrypted file format on the previous page.</string>
+         </property>
+         <property name="wordWrap">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
+
Index: kdebase-runtime-4.3.5/kwalletd/kwalletwizardpagepasswordgpg.ui
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/kwalletwizardpagepasswordgpg.ui
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>KWalletWizardPagePasswordGpg</class>
+ <widget class="QWidget" name="KWalletWizardPagePasswordGpg">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>448</width>
+    <height>385</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QLabel" name="textLabel3">
+     <property name="text">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Various applications may attempt to use the KDE wallet to store passwords or other information such as web form data and cookies. If you would like these applications to use the wallet, you must enable it now and choose method for its encryption.&lt;/p&gt;&lt;p&gt;GPG method is more secure, but you must have configured at least one encrypting key on your system.&lt;/p&gt;&lt;p&gt;If you choose the classic format, be warned that the password you choose &lt;span style=&quot; font-style:italic;&quot;&gt;cannot&lt;/span&gt; be recovered if it is lost, and will allow anyone who knows it to obtain all the information contained in the wallet.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="textFormat">
+      <enum>Qt::RichText</enum>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="_useWallet">
+     <property name="text">
+      <string>Yes, I wish to use the KDE wallet to store my personal information.</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="_groupBox">
+     <property name="enabled">
+      <bool>false</bool>
+     </property>
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string>What kind of encryption do you wish?</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QRadioButton" name="_radioGpg">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="text">
+         <string>Use GPG encryption, for better protection</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="_radioBlowfish">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="text">
+         <string>Classic, blowfish encrypted file</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
+        <item>
+         <spacer>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>28</width>
+            <height>28</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout">
+          <item>
+           <layout class="QVBoxLayout">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="textLabel1_3">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="text">
+               <string>Enter a new password:</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask</set>
+              </property>
+              <property name="buddy">
+               <cstring>_pass1</cstring>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="textLabel2_3">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="text">
+               <string>Verify password:</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask</set>
+              </property>
+              <property name="buddy">
+               <cstring>_pass2</cstring>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QVBoxLayout">
+            <property name="spacing">
+             <number>6</number>
+            </property>
+            <property name="margin">
+             <number>0</number>
+            </property>
+            <item>
+             <widget class="KLineEdit" name="_pass1">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="echoMode">
+               <enum>QLineEdit::Password</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="KLineEdit" name="_pass2">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
+              <property name="echoMode">
+               <enum>QLineEdit::Password</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <spacer>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeType">
+           <enum>QSizePolicy::Expanding</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>98</width>
+            <height>18</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QLabel" name="_matchLabel">
+        <property name="text">
+         <string/>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignAbsolute|Qt::AlignBottom|Qt::AlignCenter|Qt::AlignHCenter|Qt::AlignHorizontal_Mask|Qt::AlignJustify|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing|Qt::AlignVCenter|Qt::AlignVertical_Mask</set>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>31</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header>klineedit.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>_radioBlowfish</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>textLabel1_3</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>239</x>
+     <y>220</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>213</x>
+     <y>249</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_radioBlowfish</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>_pass1</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>239</x>
+     <y>220</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>331</x>
+     <y>249</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_radioBlowfish</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>textLabel2_3</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>239</x>
+     <y>220</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>142</x>
+     <y>277</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_radioBlowfish</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>_pass2</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>239</x>
+     <y>220</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>331</x>
+     <y>277</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_radioBlowfish</sender>
+   <signal>clicked()</signal>
+   <receiver>_pass1</receiver>
+   <slot>setFocus()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>239</x>
+     <y>220</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>331</x>
+     <y>249</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_useWallet</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>_groupBox</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>42</x>
+     <y>112</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>33</x>
+     <y>193</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_useWallet</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>_radioGpg</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>50</x>
+     <y>112</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>63</x>
+     <y>166</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_useWallet</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>_radioBlowfish</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>85</x>
+     <y>112</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>97</x>
+     <y>220</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
+
Index: kdebase-runtime-4.3.5/kwalletd/knewwalletdialog.cpp
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/knewwalletdialog.cpp
@@ -0,0 +1,187 @@
+/**
+  * This file is part of the KDE project
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Library General Public
+  * License version 2 as published by the Free Software Foundation.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Library General Public License for more details.
+  *
+  * You should have received a copy of the GNU Library General Public License
+  * along with this library; see the file COPYING.LIB.  If not, write to
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  * Boston, MA 02110-1301, USA.
+  */
+
+#include "knewwalletdialog.h"
+#include <klocalizedstring.h>
+#include <QLabel>
+#include <QTextDocument>
+#include <QTimer>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <gpgme.h>
+#include <gpgme++/context.h>
+#include <gpgme++/key.h>
+#include <gpgme++/keylistresult.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+Q_DECLARE_METATYPE(GpgME::Key)
+
+namespace KWallet {
+
+KNewWalletDialog::KNewWalletDialog(const QString &appName, const QString &walletName, QWidget* parent):
+    QWizard(parent), _intro(0), _introId(0), _gpg(0), _gpgId(0)
+{
+    setOption(HaveFinishButtonOnEarlyPages);
+    _intro = new KNewWalletDialogIntro(appName, walletName, this);
+    _introId = addPage(_intro);
+
+    _gpg = new KNewWalletDialogGpg(appName, walletName, this);
+    _gpgId = addPage(_gpg);
+}
+
+bool KNewWalletDialog::isBlowfish() const
+{
+    return _intro->isBlowfish();
+}
+
+GpgME::Key KNewWalletDialog::gpgKey() const
+{
+    QVariant varKey = field("key");
+    return varKey.value< GpgME::Key >();
+}
+
+KNewWalletDialogIntro::KNewWalletDialogIntro(const QString& appName, const QString& walletName, QWidget* parent): QWizardPage(parent)
+{
+    _ui.setupUi(this);
+    if (appName.isEmpty()){
+        _ui.labelIntro->setText(i18n("<qt>KDE has requested to create a new wallet named '<b>%1</b>'. This is used to store sensitive data in a secure fashion. Please choose the new wallet's type below or click cancel to deny the application's request.</qt>", Qt::escape(walletName)));
+    } else {
+        _ui.labelIntro->setText(i18n("<qt>The application '<b>%1</b>' has requested to create a new wallet named '<b>%2</b>'. This is used to store sensitive data in a secure fashion. Please choose the new wallet's type below or click cancel to deny the application's request.</qt>", Qt::escape(appName), Qt::escape(walletName)));
+    }
+}
+
+void KNewWalletDialogIntro::onBlowfishToggled(bool blowfish)
+{
+    setFinalPage(blowfish);
+}
+
+
+bool KNewWalletDialogIntro::isBlowfish() const
+{
+    return _ui.radioBlowfish->isChecked();
+}
+
+int KNewWalletDialogIntro::nextId() const
+{
+    if (isBlowfish()){
+        return -1;
+    } else {
+        return qobject_cast< const KNewWalletDialog* >(wizard())->gpgId();
+    }
+}
+
+KNewWalletDialogGpg::KNewWalletDialogGpg(const QString& appName, const QString& walletName, QWidget* parent):
+    QWizardPage(parent), _alreadyInitialized(false), _complete(false)
+{
+    _ui.setupUi(this);
+}
+
+struct AddKeyToList {
+    QTableWidget *_list;
+    int _row;
+    AddKeyToList(QTableWidget *list) : _list(list), _row(0) {}
+    void operator()( const GpgME::Key &k) {
+        GpgME::UserID uid = k.userID(0);
+        QString name(uid.name());
+        if (uid.comment()){
+            name = QString("%1 (%2)").arg(name).arg(uid.comment());
+        }
+        _list->setItem(_row, 0, new QTableWidgetItem(name));
+        _list->setItem(_row, 1, new QTableWidgetItem(uid.email()));
+        _list->setItem(_row, 2, new QTableWidgetItem(k.shortKeyID()));
+        QVariant varKey;
+        varKey.setValue(k);
+        _list->item(_row, 0)->setData(Qt::UserRole, varKey);
+        ++_row;
+    }
+};
+
+void KNewWalletDialogGpg::initializePage()
+{
+    if (_alreadyInitialized)
+        return;
+
+    registerField("key", this);
+
+    GpgME::initializeLibrary();
+    GpgME::Error err = GpgME::checkEngine(GpgME::OpenPGP);
+    if (err){
+        kDebug() << "OpenPGP not supported on your system!";
+        KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
+        emit completeChanged();
+        return;
+    }
+    boost::shared_ptr< GpgME::Context >   _ctx( GpgME::Context::createForProtocol(GpgME::OpenPGP) );
+    if (0 == _ctx) {
+        KMessageBox::error(this, i18n("The QGpgME library failed to initialize for the OpenPGP protocol. Please check your system's configuration then try again."));
+        emit completeChanged();
+        return;
+    }
+    _ctx->setKeyListMode(GpgME::Local);
+
+    std::vector< GpgME::Key > keys;
+    int row =0;
+    err = _ctx->startKeyListing();
+    while (!err) {
+        GpgME::Key k = _ctx->nextKey(err);
+        if (err)
+            break;
+        if (!k.isInvalid() && k.canEncrypt() && (k.ownerTrust() == GpgME::Key::Ultimate)) {
+            keys.push_back(k);
+        }
+    }
+    _ctx->endKeyListing();
+
+    if (keys.size() == 0) {
+        KMessageBox::error(this, i18n("Seems that your system has no keys suitable for encryption. Please set-up at least an encryption key, then try again."));
+        emit completeChanged();
+        return;
+    }
+
+    _ui.listCertificates->setRowCount(keys.size());
+    std::for_each(keys.begin(), keys.end(), AddKeyToList(_ui.listCertificates));
+    _ui.listCertificates->resizeColumnsToContents();
+    _ui.listCertificates->setCurrentCell(0, 0);
+
+    _alreadyInitialized = true;
+}
+
+void KNewWalletDialogGpg::onItemSelectionChanged()
+{
+    _complete = _ui.listCertificates->currentRow() >= 0;
+    QVariant varKey = _ui.listCertificates->item(_ui.listCertificates->currentRow(), 0)->data(Qt::UserRole);
+    setField("key", varKey);
+    emit completeChanged();
+}
+
+bool KNewWalletDialogGpg::isComplete() const
+{
+    return _complete;
+}
+
+bool KNewWalletDialogGpg::validateCurrentPage()
+{
+    return false;
+}
+
+
+} // namespace
+#include "moc_knewwalletdialog.cpp"
+
Index: kdebase-runtime-4.3.5/kwalletd/knewwalletdialog.h
===================================================================
--- /dev/null
+++ kdebase-runtime-4.3.5/kwalletd/knewwalletdialog.h
@@ -0,0 +1,82 @@
+/**
+  * This file is part of the KDE project
+  * Copyright (C) 2013 Valentin Rusu <kde@rusu.info>
+  *
+  * This library is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Library General Public
+  * License version 2 as published by the Free Software Foundation.
+  *
+  * This library is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Library General Public License for more details.
+  *
+  * You should have received a copy of the GNU Library General Public License
+  * along with this library; see the file COPYING.LIB.  If not, write to
+  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  * Boston, MA 02110-1301, USA.
+  */
+#ifndef KNEWWALLETDIALOG_H
+#define KNEWWALLETDIALOG_H
+
+#include <QWizard>
+
+#include "ui_knewwalletdialogintro.h"
+#include "ui_knewwalletdialoggpg.h"
+#include <boost/shared_ptr.hpp>
+
+namespace GpgME {
+class Key;
+}
+
+namespace KWallet {
+
+class KNewWalletDialogIntro;
+class KNewWalletDialogGpg;
+
+class KNewWalletDialog : public QWizard {
+    Q_OBJECT
+public:
+    KNewWalletDialog(const QString &appName, const QString &walletName, QWidget* parent = 0);
+
+    bool isBlowfish() const;
+    int gpgId() const { return _gpgId; }
+    GpgME::Key gpgKey() const;
+private:
+    KNewWalletDialogIntro   *_intro;
+    int                     _introId;
+    KNewWalletDialogGpg     *_gpg;
+    int                     _gpgId;
+};
+
+class KNewWalletDialogIntro : public QWizardPage {
+    Q_OBJECT
+public:
+    KNewWalletDialogIntro(const QString &appName, const QString &walletName, QWidget* parent = 0);
+    bool isBlowfish() const;
+    virtual int nextId() const;
+protected Q_SLOTS:
+    void onBlowfishToggled(bool);
+private:
+    Ui_KNewWalletDialogIntro _ui;
+};
+
+class KNewWalletDialogGpg : public QWizardPage {
+    Q_OBJECT
+public:
+    KNewWalletDialogGpg(const QString &appName, const QString &walletName, QWidget* parent = 0);
+    virtual void initializePage();
+    virtual bool isComplete() const;
+    virtual bool validateCurrentPage();
+protected Q_SLOTS:
+    void onItemSelectionChanged();
+private:
+    bool                    _alreadyInitialized;
+    Ui_KNewWalletDialogGpg  _ui;
+    bool                    _complete;
+};
+
+} // namespace
+
+#endif // KNEWWALLETDIALOG_H
+
