Implements KDBX4 format with Argon2 KDF

* Adds KDBX4 reader/writer interfaces
* Adds KDBX4 XML reader/write interfaces
* Implements test cases for KDBX4
* Fully compatible with KeePass2
* Corrects minor issues with Argon2 KDF
This commit is contained in:
Jonathan White
2018-01-05 10:41:29 -05:00
parent 7dba788d09
commit bef7ba2cfe
36 changed files with 3305 additions and 51 deletions

View File

@@ -110,6 +110,9 @@ add_unit_test(NAME testgroup SOURCES TestGroup.cpp
add_unit_test(NAME testkdbx3xmlreader SOURCES TestKeePass2XmlReader.cpp TestKdbx3XmlReader.cpp
LIBS ${TEST_LIBRARIES})
add_unit_test(NAME testkdbx4xmlreader SOURCES TestKeePass2XmlReader.cpp TestKdbx4XmlReader.cpp
LIBS ${TEST_LIBRARIES})
add_unit_test(NAME testkeys SOURCES TestKeys.cpp
LIBS ${TEST_LIBRARIES})

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QTest>
#include "TestKeePass2XmlReader.h"
QTEST_GUILESS_MAIN(TestKdbx4XmlReader)

View File

@@ -155,3 +155,26 @@ void TestKeePass2Reader::testFormat300()
delete db;
}
void TestKeePass2Reader::testFormat400()
{
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format400.kdbx");
CompositeKey key;
key.addKey(PasswordKey("t"));
KeePass2Reader reader;
Database* db = reader.readDatabase(filename, key);
QVERIFY(db);
QVERIFY(!reader.hasError());
QCOMPARE(db->rootGroup()->name(), QString("Format400"));
QCOMPARE(db->metadata()->name(), QString("Format400"));
QCOMPARE(db->rootGroup()->entries().size(), 1);
Entry* entry = db->rootGroup()->entries().at(0);
QCOMPARE(entry->title(), QString("Format400"));
QCOMPARE(entry->username(), QString("Format400"));
QCOMPARE(entry->attributes()->keys().size(), 6);
QCOMPARE(entry->attributes()->value("Format400"), QString("Format400"));
QCOMPARE(entry->attachments()->keys().size(), 1);
QCOMPARE(entry->attachments()->value("Format400"), QByteArray("Format400\n"));
}

View File

@@ -32,6 +32,7 @@ private slots:
void testBrokenHeaderHash();
void testFormat200();
void testFormat300();
void testFormat400();
};
#endif // KEEPASSX_TESTKEEPASS2READER_H

View File

@@ -27,6 +27,8 @@
#include "crypto/Crypto.h"
#include "format/Kdbx3XmlReader.h"
#include "format/Kdbx3XmlWriter.h"
#include "format/Kdbx4XmlReader.h"
#include "format/Kdbx4XmlWriter.h"
#include "config-keepassx-tests.h"
namespace QTest {
@@ -89,6 +91,18 @@ void TestKdbx3XmlReader::initTestCase()
QVERIFY(!reader.hasError());
}
void TestKdbx4XmlReader::initTestCase()
{
QVERIFY(Crypto::init());
Kdbx4XmlReader reader;
reader.setStrictMode(true);
QString xmlFile = QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml");
m_db = reader.readDatabase(xmlFile);
QVERIFY(m_db);
QVERIFY(!reader.hasError());
}
void TestKdbx3XmlReader::readDatabase(QString path, bool strictMode, Database*& db, bool& hasError, QString& errorString)
{
Kdbx3XmlReader reader;
@@ -115,6 +129,32 @@ void TestKdbx3XmlReader::writeDatabase(QBuffer* buf, Database* db, bool& hasErro
errorString = writer.errorString();
}
void TestKdbx4XmlReader::readDatabase(QString path, bool strictMode, Database*& db, bool& hasError, QString& errorString)
{
Kdbx4XmlReader reader;
reader.setStrictMode(strictMode);
db = reader.readDatabase(path);
hasError = reader.hasError();
errorString = reader.errorString();
}
void TestKdbx4XmlReader::readDatabase(QBuffer* buf, bool strictMode, Database*& db, bool& hasError, QString& errorString)
{
Kdbx4XmlReader reader;
reader.setStrictMode(strictMode);
db = reader.readDatabase(buf);
hasError = reader.hasError();
errorString = reader.errorString();
}
void TestKdbx4XmlReader::writeDatabase(QBuffer* buf, Database* db, bool& hasError, QString& errorString)
{
Kdbx4XmlWriter writer;
writer.writeDatabase(buf, db);
hasError = writer.hasError();
errorString = writer.errorString();
}
void TestKeePass2XmlReader::testMetadata()
{
QCOMPARE(m_db->metadata()->generator(), QString("KeePass"));

View File

@@ -70,4 +70,17 @@ protected:
virtual void writeDatabase(QBuffer* buf, Database* db, bool& hasError, QString& errorString) override;
};
class TestKdbx4XmlReader : public TestKeePass2XmlReader
{
Q_OBJECT
private slots:
virtual void initTestCase() override;
protected:
virtual void readDatabase(QBuffer* buf, bool strictMode, Database*& db, bool& hasError, QString& errorString) override;
virtual void readDatabase(QString path, bool strictMode, Database*& db, bool& hasError, QString& errorString) override;
virtual void writeDatabase(QBuffer* buf, Database* db, bool& hasError, QString& errorString) override;
};
#endif // KEEPASSX_TESTKEEPASS2XMLREADER_H

BIN
tests/data/Format400.kdbx Normal file

Binary file not shown.