From cf4e574c50b6cddf10ee40f6b7a1626cc8518a12 Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Thu, 10 May 2012 21:06:33 +0200 Subject: [PATCH] Support Twofish encrypted KeePass 1 databases. Refs #2 --- src/crypto/SymmetricCipher.cpp | 1 + src/crypto/SymmetricCipher.h | 1 + src/crypto/SymmetricCipherGcrypt.cpp | 18 ++++++++++++++++-- src/crypto/SymmetricCipherGcrypt.h | 1 + src/format/KeePass1.h | 2 -- src/format/KeePass1Reader.cpp | 3 ++- tests/TestKeePass1Reader.cpp | 17 +++++++++++++++++ tests/TestKeePass1Reader.h | 1 + tests/data/Twofish.kdb | Bin 0 -> 620 bytes 9 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 tests/data/Twofish.kdb diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp index 0e50dd4ad..383b3024f 100644 --- a/src/crypto/SymmetricCipher.cpp +++ b/src/crypto/SymmetricCipher.cpp @@ -38,6 +38,7 @@ SymmetricCipherBackend* SymmetricCipher::createBackend(SymmetricCipher::Algorith { switch (algo) { case SymmetricCipher::Aes256: + case SymmetricCipher::Twofish: return new SymmetricCipherGcrypt(algo, mode, direction); case SymmetricCipher::Salsa20: diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index c5c67543a..2a9d910ae 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -29,6 +29,7 @@ public: enum Algorithm { Aes256, + Twofish, Salsa20 }; diff --git a/src/crypto/SymmetricCipherGcrypt.cpp b/src/crypto/SymmetricCipherGcrypt.cpp index fabe3c4d9..4324a28a0 100644 --- a/src/crypto/SymmetricCipherGcrypt.cpp +++ b/src/crypto/SymmetricCipherGcrypt.cpp @@ -21,12 +21,11 @@ SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipher::Direction direction) - : m_algo(GCRY_CIPHER_AES256) + : m_algo(gcryptAlgo(algo)) , m_mode(gcryptMode(mode)) , m_direction(direction) { Q_ASSERT(Crypto::initalized()); - Q_ASSERT(algo == SymmetricCipher::Aes256); } SymmetricCipherGcrypt::~SymmetricCipherGcrypt() @@ -34,6 +33,21 @@ SymmetricCipherGcrypt::~SymmetricCipherGcrypt() gcry_cipher_close(m_ctx); } +int SymmetricCipherGcrypt::gcryptAlgo(SymmetricCipher::Algorithm algo) +{ + switch (algo) { + case SymmetricCipher::Aes256: + return GCRY_CIPHER_AES256; + + case SymmetricCipher::Twofish: + return GCRY_CIPHER_TWOFISH; + + default: + Q_ASSERT(false); + return -1; + } +} + int SymmetricCipherGcrypt::gcryptMode(SymmetricCipher::Mode mode) { switch (mode) { diff --git a/src/crypto/SymmetricCipherGcrypt.h b/src/crypto/SymmetricCipherGcrypt.h index 3af7c705b..2b255df5d 100644 --- a/src/crypto/SymmetricCipherGcrypt.h +++ b/src/crypto/SymmetricCipherGcrypt.h @@ -41,6 +41,7 @@ public: int blockSize() const; private: + static int gcryptAlgo(SymmetricCipher::Algorithm algo); static int gcryptMode(SymmetricCipher::Mode mode); gcry_cipher_hd_t m_ctx; diff --git a/src/format/KeePass1.h b/src/format/KeePass1.h index 7e656c0cd..0a1c56e56 100644 --- a/src/format/KeePass1.h +++ b/src/format/KeePass1.h @@ -20,8 +20,6 @@ #include -#include "core/Uuid.h" - namespace KeePass1 { const quint32 SIGNATURE_1 = 0x9AA2D903; diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 6d5b294f4..de219325e 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -272,7 +272,8 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q SymmetricCipher::Cbc, SymmetricCipher::Decrypt, finalKey, m_encryptionIV)); } else { - // TODO twofish + cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Twofish, + SymmetricCipher::Cbc, SymmetricCipher::Decrypt, finalKey, m_encryptionIV)); } cipherStream->open(QIODevice::ReadOnly); diff --git a/tests/TestKeePass1Reader.cpp b/tests/TestKeePass1Reader.cpp index cb0332fb8..ea4a7d64a 100644 --- a/tests/TestKeePass1Reader.cpp +++ b/tests/TestKeePass1Reader.cpp @@ -179,6 +179,23 @@ void TestKeePass1Reader::testCompositeKey() delete db; } +void TestKeePass1Reader::testTwofish() +{ + QString name = "Twofish"; + + KeePass1Reader reader; + + QString dbFilename = QString("%1/%2.kdb").arg(QString(KEEPASSX_TEST_DATA_DIR), name); + + Database* db = reader.readDatabase(dbFilename, "masterpw", QByteArray()); + QVERIFY(db); + QVERIFY(!reader.hasError()); + QCOMPARE(db->rootGroup()->children().size(), 1); + QCOMPARE(db->rootGroup()->children().at(0)->name(), name); + + delete db; +} + void TestKeePass1Reader::cleanupTestCase() { delete m_db; diff --git a/tests/TestKeePass1Reader.h b/tests/TestKeePass1Reader.h index 8a8da4e0f..fe1c435fd 100644 --- a/tests/TestKeePass1Reader.h +++ b/tests/TestKeePass1Reader.h @@ -35,6 +35,7 @@ private Q_SLOTS: void testFileKey(); void testFileKey_data(); void testCompositeKey(); + void testTwofish(); void cleanupTestCase(); private: diff --git a/tests/data/Twofish.kdb b/tests/data/Twofish.kdb new file mode 100644 index 0000000000000000000000000000000000000000..eb4ae6dc5af9bd148418e987355260b409668a37 GIT binary patch literal 620 zcmV-y0+am%*`k_d`%AS60000200RK=bMB}ca~Zi4rPeeQ$NYp~>QG<2?bXI1ja##Q z=Q?Wv000020001Oy6@hU4O5=-`lEc{m#D4}4L|gS^5r<+8VL><7)r4qL>eqX;Zuu1 z;E?CA+;3ch^Go;hO6-2fQq|B~mlK2#CjbC*CyC`nJc7h+Ini{=19b?+6~-ic4wz|W zrYF69(rOmnwb~)Vm?o?1eaX^U_B*!qoWs9)goUWe!&Z%67a*$c&bjKj01eWLuXKb{ zs<$4_9a;DS+`psl4+AQuvkmZ0+U2`RozY0yQ&`t;Te#T47{R}K-Yq6deFpxEPVwvAg76^EH8 z3fzIFP04vWzyiyr5E(nMCxze?DN!mS+JBY~NuZ#h1#>OS1@9s^CuJ>j`MoGouPmAK zDn^+;R@^k7ww5^g4vwUQ`rTH>2k)XO6zP+o@VU~IJ0YR@-E!iNdH79V-x@+7?CFIH z#v8VxQY4{Uiz@^FeXE}n{XIVDb4>jND5$#px1YG{lr7>P2v0*11G*A|9ChYj`qiB; GU}zDBlPvcD literal 0 HcmV?d00001