Set master key after reading the database.

This commit is contained in:
Felix Geyer 2012-05-10 22:46:36 +02:00
parent 9d8e276950
commit 366d8a0f0e
5 changed files with 68 additions and 27 deletions

View file

@ -30,6 +30,8 @@
#include "crypto/CryptoHash.h" #include "crypto/CryptoHash.h"
#include "format/KeePass1.h" #include "format/KeePass1.h"
#include "keys/CompositeKey.h" #include "keys/CompositeKey.h"
#include "keys/FileKey.h"
#include "keys/PasswordKey.h"
#include "streams/SymmetricCipherStream.h" #include "streams/SymmetricCipherStream.h"
class KeePass1Key : public CompositeKey class KeePass1Key : public CompositeKey
@ -52,8 +54,26 @@ KeePass1Reader::KeePass1Reader()
} }
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password,
const QByteArray& keyfileData) QIODevice* keyfileDevice)
{ {
QByteArray keyfileData;
FileKey newFileKey;
if (keyfileDevice) {
keyfileData = readKeyfile(keyfileDevice);
if (keyfileData.isEmpty()) {
return 0;
}
if (!keyfileDevice->seek(0)) {
return 0;
}
if (!newFileKey.load(keyfileDevice)) {
return 0;
}
}
QScopedPointer<Database> db(new Database()); QScopedPointer<Database> db(new Database());
QScopedPointer<Group> tmpParent(new Group()); QScopedPointer<Group> tmpParent(new Group());
m_db = db.data(); m_db = db.data();
@ -197,22 +217,41 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
entry->setUpdateTimeinfo(true); entry->setUpdateTimeinfo(true);
} }
CompositeKey key;
if (!password.isEmpty()) {
key.addKey(PasswordKey(password));
}
if (keyfileDevice) {
key.addKey(newFileKey);
}
db->setKey(key);
return db.take(); return db.take();
} }
Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password, Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password,
const QByteArray& keyfileData) const QString& keyfileName)
{ {
QFile file(filename); QFile dbFile(filename);
if (!file.open(QFile::ReadOnly)) { if (!dbFile.open(QFile::ReadOnly)) {
raiseError(file.errorString()); raiseError(dbFile.errorString());
return 0; return 0;
} }
QScopedPointer<Database> db(readDatabase(&file, password, keyfileData)); QScopedPointer<QFile> keyFile;
if (!keyfileName.isEmpty()) {
keyFile.reset(new QFile(keyfileName));
if (!keyFile->open(QFile::ReadOnly)) {
raiseError(keyFile->errorString());
return 0;
}
}
if (file.error() != QFile::NoError) { QScopedPointer<Database> db(readDatabase(&dbFile, password, keyFile.data()));
raiseError(file.errorString());
if (dbFile.error() != QFile::NoError) {
raiseError(dbFile.errorString());
return 0; return 0;
} }

View file

@ -35,10 +35,9 @@ class KeePass1Reader
public: public:
KeePass1Reader(); KeePass1Reader();
Database* readDatabase(QIODevice* device, const QString& password, Database* readDatabase(QIODevice* device, const QString& password,
const QByteArray& keyfileData); QIODevice* keyfileDevice);
Database* readDatabase(const QString& filename, const QString& password, Database* readDatabase(const QString& filename, const QString& password,
const QByteArray& keyfileData); const QString& keyfileName);
static QByteArray readKeyfile(QIODevice* device);
bool hasError(); bool hasError();
QString errorString(); QString errorString();
@ -61,6 +60,7 @@ private:
bool parseGroupTreeState(const QByteArray& data); bool parseGroupTreeState(const QByteArray& data);
bool parseCustomIcons4(const QByteArray& data); bool parseCustomIcons4(const QByteArray& data);
void raiseError(const QString& str); void raiseError(const QString& str);
static QByteArray readKeyfile(QIODevice* device);
static QDateTime dateFromPackedStruct(const QByteArray& data); static QDateTime dateFromPackedStruct(const QByteArray& data);
static bool isMetaStream(const Entry* entry); static bool isMetaStream(const Entry* entry);

View file

@ -17,7 +17,7 @@
#include "TestKeePass1Reader.h" #include "TestKeePass1Reader.h"
#include <QtCore/QFile> #include <QtCore/QBuffer>
#include <QtTest/QTest> #include <QtTest/QTest>
#include "config-keepassx-tests.h" #include "config-keepassx-tests.h"
@ -28,6 +28,10 @@
#include "core/Metadata.h" #include "core/Metadata.h"
#include "crypto/Crypto.h" #include "crypto/Crypto.h"
#include "format/KeePass1Reader.h" #include "format/KeePass1Reader.h"
#include "format/KeePass2Reader.h"
#include "format/KeePass2Writer.h"
#include "keys/FileKey.h"
#include "keys/PasswordKey.h"
void TestKeePass1Reader::initTestCase() void TestKeePass1Reader::initTestCase()
{ {
@ -36,7 +40,7 @@ void TestKeePass1Reader::initTestCase()
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/basic.kdb"); QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/basic.kdb");
KeePass1Reader reader; KeePass1Reader reader;
m_db = reader.readDatabase(filename, "masterpw", QByteArray()); m_db = reader.readDatabase(filename, "masterpw", 0);
QVERIFY(m_db); QVERIFY(m_db);
QVERIFY(!reader.hasError()); QVERIFY(!reader.hasError());
} }
@ -98,6 +102,12 @@ void TestKeePass1Reader::testBasic()
QCOMPARE(group2->iconNumber(), 19); QCOMPARE(group2->iconNumber(), 19);
} }
void TestKeePass1Reader::testMasterKey()
{
QVERIFY(m_db->hasKey());
QCOMPARE(m_db->transformRounds(), static_cast<quint64>(713));
}
void TestKeePass1Reader::testCustomIcons() void TestKeePass1Reader::testCustomIcons()
{ {
QCOMPARE(m_db->metadata()->customIcons().size(), 1); QCOMPARE(m_db->metadata()->customIcons().size(), 1);
@ -136,12 +146,7 @@ void TestKeePass1Reader::testFileKey()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name); QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
QString keyFilename = QString("%1/%2.key").arg(QString(KEEPASSX_TEST_DATA_DIR), name); QString keyFilename = QString("%1/%2.key").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
QFile file(keyFilename); Database* db = reader.readDatabase(dbFilename, QString(), keyFilename);
QVERIFY(file.open(QIODevice::ReadOnly));
QByteArray keyData = KeePass1Reader::readKeyfile(&file);
QVERIFY(!keyData.isEmpty());
Database* db = reader.readDatabase(dbFilename, QString(), keyData);
QVERIFY(db); QVERIFY(db);
QVERIFY(!reader.hasError()); QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1); QCOMPARE(db->rootGroup()->children().size(), 1);
@ -167,12 +172,7 @@ void TestKeePass1Reader::testCompositeKey()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name); QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
QString keyFilename = QString("%1/FileKeyHex.key").arg(QString(KEEPASSX_TEST_DATA_DIR)); QString keyFilename = QString("%1/FileKeyHex.key").arg(QString(KEEPASSX_TEST_DATA_DIR));
QFile file(keyFilename); Database* db = reader.readDatabase(dbFilename, "mypassword", keyFilename);
QVERIFY(file.open(QIODevice::ReadOnly));
QByteArray keyData = KeePass1Reader::readKeyfile(&file);
QVERIFY(!keyData.isEmpty());
Database* db = reader.readDatabase(dbFilename, "mypassword", keyData);
QVERIFY(db); QVERIFY(db);
QVERIFY(!reader.hasError()); QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1); QCOMPARE(db->rootGroup()->children().size(), 1);
@ -189,7 +189,7 @@ void TestKeePass1Reader::testTwofish()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name); QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
Database* db = reader.readDatabase(dbFilename, "masterpw", QByteArray()); Database* db = reader.readDatabase(dbFilename, "masterpw", 0);
QVERIFY(db); QVERIFY(db);
QVERIFY(!reader.hasError()); QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1); QCOMPARE(db->rootGroup()->children().size(), 1);
@ -207,7 +207,7 @@ void TestKeePass1Reader::testCP1252Password()
QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name); QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name);
QString password = QString::fromUtf8("\xe2\x80\x9e\x70\x61\x73\x73\x77\x6f\x72\x64\xe2\x80\x9d"); QString password = QString::fromUtf8("\xe2\x80\x9e\x70\x61\x73\x73\x77\x6f\x72\x64\xe2\x80\x9d");
Database* db = reader.readDatabase(dbFilename, password, QByteArray()); Database* db = reader.readDatabase(dbFilename, password, 0);
QVERIFY(db); QVERIFY(db);
QVERIFY(!reader.hasError()); QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->children().size(), 1); QCOMPARE(db->rootGroup()->children().size(), 1);

View file

@ -22,6 +22,7 @@
#include <QtCore/QObject> #include <QtCore/QObject>
class Database; class Database;
class QIODevice;
class TestKeePass1Reader : public QObject class TestKeePass1Reader : public QObject
{ {
@ -30,6 +31,7 @@ class TestKeePass1Reader : public QObject
private Q_SLOTS: private Q_SLOTS:
void initTestCase(); void initTestCase();
void testBasic(); void testBasic();
void testMasterKey();
void testCustomIcons(); void testCustomIcons();
void testGroupExpanded(); void testGroupExpanded();
void testFileKey(); void testFileKey();

Binary file not shown.