mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-08-19 03:28:25 -04:00
Set master key after reading the database.
This commit is contained in:
parent
9d8e276950
commit
366d8a0f0e
5 changed files with 68 additions and 27 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
Loading…
Add table
Add a link
Reference in a new issue