Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFelix Geyer <debfx@fobos.de>2010-09-14 01:24:36 +0400
committerFelix Geyer <debfx@fobos.de>2010-09-14 01:24:36 +0400
commit9f282928e85ea9ff115ad41ea2b93eac0e07ad25 (patch)
tree0fd6fba15d7529132cbdc6ccb0eee39faf81c56a /src
parentbb6ae3a014636b1ae686c47ccb09b15d4805bee3 (diff)
Implement reading encrypted kdbx files.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt7
-rw-r--r--src/core/Endian.cpp134
-rw-r--r--src/core/Endian.h43
-rw-r--r--src/format/DatabaseReader.h34
-rw-r--r--src/format/DatabaseWriter.h32
-rw-r--r--src/format/KeePass2.h53
-rw-r--r--src/format/KeePass2Reader.cpp273
-rw-r--r--src/format/KeePass2Reader.h70
-rw-r--r--src/format/KeePass2XmlReader.cpp2
-rw-r--r--src/format/KeePass2XmlReader.h3
-rw-r--r--src/format/KeePass2XmlWriter.h3
-rw-r--r--src/keys/CompositeKey.cpp113
-rw-r--r--src/keys/CompositeKey.h39
-rw-r--r--src/keys/Key.h30
-rw-r--r--src/keys/PasswordKey.cpp35
-rw-r--r--src/keys/PasswordKey.h36
-rw-r--r--src/streams/HashedBlockStream.cpp145
-rw-r--r--src/streams/HashedBlockStream.h52
-rw-r--r--src/streams/LayeredStream.cpp72
-rw-r--r--src/streams/LayeredStream.h44
-rw-r--r--src/streams/SymmetricCipherStream.cpp92
-rw-r--r--src/streams/SymmetricCipherStream.h49
22 files changed, 1290 insertions, 71 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0a1c0ba91..5fa79d081 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -19,6 +19,7 @@ configure_file( config-keepassx.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keepa
set(keepassx_SOURCES
core/Database.cpp
+ core/Endian.cpp
core/Entry.cpp
core/Group.cpp
core/Metadata.cpp
@@ -28,6 +29,7 @@ set(keepassx_SOURCES
crypto/CryptoHash.cpp
crypto/Random.cpp
crypto/SymmetricCipher.cpp
+ format/KeePass2Reader.cpp
format/KeePass2XmlReader.cpp
format/KeePass2XmlWriter.cpp
gui/DatabaseWidget.cpp
@@ -35,6 +37,11 @@ set(keepassx_SOURCES
gui/EntryView.cpp
gui/GroupModel.cpp
gui/GroupView.cpp
+ keys/CompositeKey.cpp
+ keys/PasswordKey.cpp
+ streams/HashedBlockStream.cpp
+ streams/LayeredStream.cpp
+ streams/SymmetricCipherStream.cpp
)
automoc4_add_library( keepassx_core STATIC ${keepassx_SOURCES} )
diff --git a/src/core/Endian.cpp b/src/core/Endian.cpp
new file mode 100644
index 000000000..8fca50f12
--- /dev/null
+++ b/src/core/Endian.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+ *
+ * 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 "Endian.h"
+
+#include <QtCore/QtEndian>
+#include <QtCore/QIODevice>
+
+namespace Endian
+{
+
+qint16 bytesToInt16(const QByteArray& ba, QSysInfo::Endian byteOrder)
+{
+ Q_ASSERT(ba.size() == 2);
+
+ if (byteOrder == QSysInfo::LittleEndian) {
+ return qFromLittleEndian<qint16>(reinterpret_cast<const uchar*>(ba.constData()));
+ }
+ else {
+ return qFromBigEndian<qint16>(reinterpret_cast<const uchar*>(ba.constData()));
+ }
+}
+
+qint32 bytesToInt32(const QByteArray& ba, QSysInfo::Endian byteOrder)
+{
+ Q_ASSERT(ba.size() == 4);
+
+ if (byteOrder == QSysInfo::LittleEndian) {
+ return qFromLittleEndian<qint32>(reinterpret_cast<const uchar*>(ba.constData()));
+ }
+ else {
+ return qFromBigEndian<qint32>(reinterpret_cast<const uchar*>(ba.constData()));
+ }
+}
+
+qint64 bytesToInt64(const QByteArray& ba, QSysInfo::Endian byteOrder)
+{
+ Q_ASSERT(ba.size() == 8);
+
+ if (byteOrder == QSysInfo::LittleEndian) {
+ return qFromLittleEndian<qint64>(reinterpret_cast<const uchar*>(ba.constData()));
+ }
+ else {
+ return qFromBigEndian<qint64>(reinterpret_cast<const uchar*>(ba.constData()));
+ }
+}
+
+quint16 bytesToUInt16(const QByteArray& ba, QSysInfo::Endian byteOrder)
+{
+ return bytesToInt16(ba, byteOrder);
+}
+
+quint32 bytesToUInt32(const QByteArray& ba, QSysInfo::Endian byteOrder)
+{
+ return bytesToInt32(ba, byteOrder);
+}
+
+quint64 bytesToUInt64(const QByteArray& ba, QSysInfo::Endian byteOrder)
+{
+ return bytesToInt64(ba, byteOrder);
+}
+
+qint16 readInt16(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
+{
+ QByteArray ba = device->read(2);
+
+ if (ba.size() != 2) {
+ *ok = false;
+ return 0;
+ }
+ else {
+ *ok = true;
+ return bytesToUInt16(ba, byteOrder);
+ }
+}
+
+qint32 readInt32(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
+{
+ QByteArray ba = device->read(4);
+
+ if (ba.size() != 4) {
+ *ok = false;
+ return 0;
+ }
+ else {
+ *ok = true;
+ return bytesToUInt32(ba, byteOrder);
+ }
+}
+
+qint64 readInt64(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
+{
+ QByteArray ba = device->read(8);
+
+ if (ba.size() != 8) {
+ *ok = false;
+ return 0;
+ }
+ else {
+ *ok = true;
+ return bytesToUInt64(ba, byteOrder);
+ }
+}
+
+quint16 readUInt16(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
+{
+ return readInt16(device, byteOrder, ok);
+}
+
+quint32 readUInt32(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
+{
+ return readInt32(device, byteOrder, ok);
+}
+
+quint64 readUInt64(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok)
+{
+ return readInt64(device, byteOrder, ok);
+}
+
+} // namespace Endian
diff --git a/src/core/Endian.h b/src/core/Endian.h
new file mode 100644
index 000000000..8958cc400
--- /dev/null
+++ b/src/core/Endian.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+ *
+ * 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/>.
+ */
+
+#ifndef KEEPASSX_ENDIAN_H
+#define KEEPASSX_ENDIAN_H
+
+#include <QtCore/QByteArray>
+#include <QtCore/QSysInfo>
+
+class QIODevice;
+
+namespace Endian
+{
+ qint16 bytesToInt16(const QByteArray& ba, QSysInfo::Endian byteOrder);
+ quint16 bytesToUInt16(const QByteArray& ba, QSysInfo::Endian byteOrder);
+ qint32 bytesToInt32(const QByteArray& ba, QSysInfo::Endian byteOrder);
+ quint32 bytesToUInt32(const QByteArray& ba, QSysInfo::Endian byteOrder);
+ qint64 bytesToInt64(const QByteArray& ba, QSysInfo::Endian byteOrder);
+ quint64 bytesToUInt64(const QByteArray& ba, QSysInfo::Endian byteOrder);
+
+ qint16 readInt16(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok);
+ quint16 readUInt16(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok);
+ qint32 readInt32(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok);
+ quint32 readUInt32(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok);
+ qint64 readInt64(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok);
+ quint64 readUInt64(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok);
+};
+
+#endif // KEEPASSX_ENDIAN_H
diff --git a/src/format/DatabaseReader.h b/src/format/DatabaseReader.h
deleted file mode 100644
index d9ea3b997..000000000
--- a/src/format/DatabaseReader.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
- *
- * 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/>.
- */
-
-#ifndef KEEPASSX_DATABASEREADER_H
-#define KEEPASSX_DATABASEREADER_H
-
-#include <QtCore/QString>
-
-class Database;
-class QIODevice;
-
-class DatabaseReader
-{
-public:
- virtual Database* readDatabase(QIODevice* device) = 0;
- virtual bool error() = 0;
- virtual QString errorString() = 0;
-};
-
-#endif // KEEPASSX_DATABASEREADER_H
diff --git a/src/format/DatabaseWriter.h b/src/format/DatabaseWriter.h
deleted file mode 100644
index 1624fad30..000000000
--- a/src/format/DatabaseWriter.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
- *
- * 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/>.
- */
-
-#ifndef KEEPASSX_DATABASEWRITER_H
-#define KEEPASSX_DATABASEWRITER_H
-
-#include <QtCore/QString>
-
-class Database;
-class QIODevice;
-
-class DatabaseWriter
-{
-public:
- virtual void writeDatabase(QIODevice* device, Database* db) = 0;
-};
-
-#endif // KEEPASSX_DATABASEWRITER_H
diff --git a/src/format/KeePass2.h b/src/format/KeePass2.h
new file mode 100644
index 000000000..0785a4eac
--- /dev/null
+++ b/src/format/KeePass2.h
@@ -0,0 +1,53 @@
+ /*
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+ *
+ * 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/>.
+ */
+
+#ifndef KEEPASSX_KEEPASS2_H
+#define KEEPASSX_KEEPASS2_H
+
+#include <QtCore/QtGlobal>
+
+namespace KeePass2
+{
+ const quint32 SIGNATURE_1 = 0x9AA2D903;
+ const quint32 SIGNATURE_2 = 0xB54BFB67;
+ const quint32 FILE_VERSION = 0x00020000;
+ const quint32 FILE_VERSION_CRITICAL_MASK = 0xFFFF0000;
+
+ enum HeaderFieldID
+ {
+ EndOfHeader = 0,
+ Comment = 1,
+ CipherID = 2,
+ CompressionFlags = 3,
+ MasterSeed = 4,
+ TransformSeed = 5,
+ TransformRounds = 6,
+ EncryptionIV = 7,
+ ProtectedStreamKey = 8,
+ StreamStartBytes = 9,
+ InnerRandomStreamID = 10
+ };
+
+ enum CompressionAlgorithm
+ {
+ CompressionNone = 0,
+ CompressionGZip = 1,
+ CompressionCount = 2
+ };
+}
+
+#endif // KEEPASSX_KEEPASS2_H
diff --git a/src/format/KeePass2Reader.cpp b/src/format/KeePass2Reader.cpp
new file mode 100644
index 000000000..23d99fb35
--- /dev/null
+++ b/src/format/KeePass2Reader.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+ *
+ * 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 "KeePass2Reader.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QFile>
+#include <QtCore/QIODevice>
+
+#include "KeePass2.h"
+#include "KeePass2XmlReader.h"
+#include "crypto/CryptoHash.h"
+#include "streams/HashedBlockStream.h"
+#include "streams/SymmetricCipherStream.h"
+
+const QSysInfo::Endian KeePass2Reader::BYTEORDER = QSysInfo::LittleEndian;
+
+Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& key)
+{
+ m_device = device;
+ m_error = false;
+ m_errorStr = QString();
+ m_headerEnd = false;
+ m_cipher = Uuid();
+
+ bool ok;
+
+ quint32 signature1 = Endian::readUInt32(m_device, BYTEORDER, &ok);
+ if (!ok || signature1 != KeePass2::SIGNATURE_1) {
+ raiseError("1");
+ return 0;
+ }
+
+ quint32 signature2 = Endian::readUInt32(m_device, BYTEORDER, &ok);
+ if (!ok || signature2 != KeePass2::SIGNATURE_2) {
+ raiseError("2");
+ return 0;
+ }
+
+ quint32 version = Endian::readUInt32(m_device, BYTEORDER, &ok) & KeePass2::FILE_VERSION_CRITICAL_MASK;
+ quint32 expectedVersion = KeePass2::FILE_VERSION & KeePass2::FILE_VERSION_CRITICAL_MASK;
+ // TODO do we support old Kdbx versions?
+ if (!ok || (version != expectedVersion)) {
+ raiseError("3");
+ return 0;
+ }
+
+ while (readHeaderField() && !error()) {
+ }
+
+ CryptoHash hash(CryptoHash::Sha256);
+ hash.addData(m_masterSeed);
+ hash.addData(key.transform(m_transformSeed, m_transformRounds));
+ QByteArray finalKey = hash.result();
+
+ SymmetricCipherStream cipherStream(device, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt, finalKey, m_encryptionIV);
+ cipherStream.open(QIODevice::ReadOnly);
+
+ QByteArray realStart = cipherStream.read(32);
+
+ if (realStart != m_streamStartBytes) {
+ raiseError("4");
+ }
+
+ HashedBlockStream hashedStream(&cipherStream);
+ hashedStream.open(QIODevice::ReadOnly);
+
+ KeePass2XmlReader xmlReader;
+ Database* db = xmlReader.readDatabase(&hashedStream);
+ return db;
+}
+
+Database* KeePass2Reader::readDatabase(const QString& filename, const CompositeKey& key)
+{
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ Database* db = readDatabase(&file, key);
+ // TODO check for QFile errors
+ return db;
+}
+
+bool KeePass2Reader::error()
+{
+ return m_error;
+}
+
+QString KeePass2Reader::errorString()
+{
+ // TODO
+ return QString();
+}
+
+void KeePass2Reader::raiseError(const QString& str)
+{
+ // TODO
+ qWarning("KeePass2Reader error: %s", qPrintable(str));
+ m_error = true;
+}
+
+bool KeePass2Reader::readHeaderField()
+{
+ QByteArray fieldIDArray = m_device->read(1);
+ if (fieldIDArray.size() != 1) {
+ raiseError("");
+ return false;
+ }
+ quint8 fieldID = fieldIDArray.at(0);
+
+ bool ok;
+ quint16 fieldLen = Endian::readUInt16(m_device, BYTEORDER, &ok);
+ if (!ok) {
+ raiseError("");
+ return false;
+ }
+
+ QByteArray fieldData;
+ if (fieldLen != 0) {
+ fieldData = m_device->read(fieldLen);
+ if (fieldData.size() != fieldLen) {
+ raiseError("");
+ return false;
+ }
+ }
+
+ switch (fieldID) {
+ case KeePass2::EndOfHeader:
+ m_headerEnd = true;
+ break;
+
+ case KeePass2::CipherID:
+ setCipher(fieldData);
+ break;
+
+ case KeePass2::CompressionFlags:
+ setCompressionFlags(fieldData);
+ break;
+
+ case KeePass2::MasterSeed:
+ setMasterSeed(fieldData);
+ break;
+
+ case KeePass2::TransformSeed:
+ setTransformSeed(fieldData);
+ break;
+
+ case KeePass2::TransformRounds:
+ setTansformRounds(fieldData);
+ break;
+
+ case KeePass2::EncryptionIV:
+ setEncryptionIV(fieldData);
+ break;
+
+ case KeePass2::ProtectedStreamKey:
+ setProtectedStreamKey(fieldData);
+ break;
+
+ case KeePass2::StreamStartBytes:
+ setStreamStartBytes(fieldData);
+ break;
+
+ case KeePass2::InnerRandomStreamID:
+ setInnerRandomStreamID(fieldData);
+ break;
+
+ default:
+ qWarning("Unknown header field read: id=%d", fieldID);
+ break;
+ }
+
+ return !m_headerEnd;
+}
+
+void KeePass2Reader::setCipher(const QByteArray& data)
+{
+ if (data.size() != Uuid::LENGTH) {
+ raiseError("");
+ }
+ else {
+ m_cipher = Uuid(data);
+ }
+}
+
+void KeePass2Reader::setCompressionFlags(const QByteArray& data)
+{
+ if (data.size() != 4) {
+ raiseError("");
+ }
+ else {
+ quint32 id = Endian::bytesToUInt32(data, BYTEORDER);
+
+ if (id >= KeePass2::CompressionCount) {
+ raiseError("");
+ }
+ else {
+ m_compression = id;
+ }
+ }
+}
+
+void KeePass2Reader::setMasterSeed(const QByteArray& data)
+{
+ if (data.size() != 32) {
+ raiseError("");
+ }
+ else {
+ m_masterSeed = data;
+ }
+}
+
+void KeePass2Reader::setTransformSeed(const QByteArray& data)
+{
+ if (data.size() != 32) {
+ raiseError("");
+ }
+ else {
+ m_transformSeed = data;
+ }
+}
+
+void KeePass2Reader::setTansformRounds(const QByteArray& data)
+{
+ if (data.size() != 8) {
+ raiseError("");
+ }
+ else {
+ m_transformRounds = Endian::bytesToUInt64(data, BYTEORDER);
+ }
+}
+
+void KeePass2Reader::setEncryptionIV(const QByteArray& data)
+{
+ if (data.size() != 16) {
+ raiseError("");
+ }
+ else {
+ m_encryptionIV = data;
+ }
+}
+
+void KeePass2Reader::setProtectedStreamKey(const QByteArray& data)
+{
+ // TODO ignore?
+}
+
+void KeePass2Reader::setStreamStartBytes(const QByteArray& data)
+{
+ if (data.size() != 32) {
+ raiseError("");
+ }
+ else {
+ m_streamStartBytes = data;
+ }
+}
+
+void KeePass2Reader::setInnerRandomStreamID(const QByteArray& data)
+{
+ // TODO ignore?
+}
diff --git a/src/format/KeePass2Reader.h b/src/format/KeePass2Reader.h
new file mode 100644
index 000000000..396348036
--- /dev/null
+++ b/src/format/KeePass2Reader.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+ *
+ * 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/>.
+ */
+
+#ifndef KEEPASSX_KEEPASS2READER_H
+#define KEEPASSX_KEEPASS2READER_H
+
+#include <QtCore/QCoreApplication>
+
+#include "core/Endian.h"
+#include "core/Uuid.h"
+#include "keys/CompositeKey.h"
+
+class Database;
+
+class KeePass2Reader
+{
+ Q_DECLARE_TR_FUNCTIONS(KeePass2Reader);
+
+public:
+ Database* readDatabase(QIODevice* device, const CompositeKey& key);
+ Database* readDatabase(const QString& filename, const CompositeKey& key);
+ bool error();
+ QString errorString();
+
+private:
+ void raiseError(const QString& str);
+
+ bool readHeaderField();
+
+ void setCipher(const QByteArray& data);
+ void setCompressionFlags(const QByteArray& data);
+ void setMasterSeed(const QByteArray& data);
+ void setTransformSeed(const QByteArray& data);
+ void setTansformRounds(const QByteArray& data);
+ void setEncryptionIV(const QByteArray& data);
+ void setProtectedStreamKey(const QByteArray& data);
+ void setStreamStartBytes(const QByteArray& data);
+ void setInnerRandomStreamID(const QByteArray& data);
+
+ static const QSysInfo::Endian BYTEORDER;
+
+ QIODevice* m_device;
+ bool m_error;
+ QString m_errorStr;
+ bool m_headerEnd;
+
+ Uuid m_cipher;
+ int m_compression;
+ QByteArray m_masterSeed;
+ QByteArray m_transformSeed;
+ quint64 m_transformRounds;
+ QByteArray m_encryptionIV;
+ QByteArray m_streamStartBytes;
+};
+
+#endif // KEEPASSX_KEEPASS2READER_H
diff --git a/src/format/KeePass2XmlReader.cpp b/src/format/KeePass2XmlReader.cpp
index 3da526854..2522d8970 100644
--- a/src/format/KeePass2XmlReader.cpp
+++ b/src/format/KeePass2XmlReader.cpp
@@ -57,7 +57,7 @@ Database* KeePass2XmlReader::readDatabase(QIODevice* device)
Database* KeePass2XmlReader::readDatabase(const QString& filename)
{
QFile file(filename);
- file.open(QIODevice::ReadOnly | QIODevice::Text);
+ file.open(QIODevice::ReadOnly);
return readDatabase(&file);
}
diff --git a/src/format/KeePass2XmlReader.h b/src/format/KeePass2XmlReader.h
index c9e715ac9..f6c4d8993 100644
--- a/src/format/KeePass2XmlReader.h
+++ b/src/format/KeePass2XmlReader.h
@@ -23,7 +23,6 @@
#include <QtCore/QXmlStreamReader>
#include <QtGui/QColor>
-#include "DatabaseReader.h"
#include "core/TimeInfo.h"
#include "core/Uuid.h"
@@ -32,7 +31,7 @@ class Entry;
class Group;
class Metadata;
-class KeePass2XmlReader : public DatabaseReader
+class KeePass2XmlReader
{
Q_DECLARE_TR_FUNCTIONS(KeePass2XmlReader);
diff --git a/src/format/KeePass2XmlWriter.h b/src/format/KeePass2XmlWriter.h
index e2149d6ef..8050697c6 100644
--- a/src/format/KeePass2XmlWriter.h
+++ b/src/format/KeePass2XmlWriter.h
@@ -23,7 +23,6 @@
#include <QtGui/QColor>
#include <QtGui/QImage>
-#include "DatabaseWriter.h"
#include "core/Database.h"
#include "core/Entry.h"
#include "core/TimeInfo.h"
@@ -32,7 +31,7 @@
class Group;
class Metadata;
-class KeePass2XmlWriter : public DatabaseWriter
+class KeePass2XmlWriter
{
public:
KeePass2XmlWriter();
diff --git a/src/keys/CompositeKey.cpp b/src/keys/CompositeKey.cpp
new file mode 100644
index 000000000..1fd5249f8
--- /dev/null
+++ b/src/keys/CompositeKey.cpp
@@ -0,0 +1,113 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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 "CompositeKey.h"
+
+#include <QtCore/QThread>
+
+#include "crypto/CryptoHash.h"
+#include "crypto/SymmetricCipher.h"
+
+class KeyTransformation : public QThread
+{
+ Q_OBJECT
+
+public:
+ KeyTransformation(const QByteArray& key, const QByteArray& seed, int rounds);
+ QByteArray result();
+
+protected:
+ void run();
+
+private:
+ QByteArray m_key;
+ QByteArray m_seed;
+ int m_rounds;
+ QByteArray m_result;
+};
+
+CompositeKey::~CompositeKey()
+{
+ qDeleteAll(m_keys);
+}
+
+CompositeKey* CompositeKey::clone() const
+{
+ return new CompositeKey(*this);
+}
+
+
+QByteArray CompositeKey::rawKey() const
+{
+ CryptoHash cryptoHash(CryptoHash::Sha256);
+
+ Q_FOREACH (Key* key, m_keys) {
+ cryptoHash.addData(key->rawKey());
+ }
+
+ return cryptoHash.result();
+}
+
+QByteArray CompositeKey::transform(const QByteArray& seed, int rounds) const
+{
+ QByteArray key = rawKey();
+
+ KeyTransformation* transform1 = new KeyTransformation(key.left(16), seed, rounds);
+ KeyTransformation* transform2 = new KeyTransformation(key.right(16), seed, rounds);
+
+ transform1->start();
+ transform2->start();
+
+ transform1->wait();
+ transform2->wait();
+
+ QByteArray transformed;
+ transformed.append(transform1->result());
+ transformed.append(transform2->result());
+
+ return CryptoHash::hash(transformed, CryptoHash::Sha256);
+}
+
+void CompositeKey::addKey(const Key& key)
+{
+ m_keys.append(key.clone());
+}
+
+KeyTransformation::KeyTransformation(const QByteArray& key, const QByteArray& seed, int rounds)
+ : m_key(key)
+ , m_seed(seed)
+ , m_rounds(rounds)
+ , m_result(key)
+{
+}
+
+void KeyTransformation::run()
+{
+ QByteArray iv(16, 0);
+ SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Encrypt, m_seed, iv);
+
+ for (int i=0; i<m_rounds; i++) {
+ cipher.processInPlace(m_result);
+ }
+}
+
+QByteArray KeyTransformation::result()
+{
+ return m_result;
+}
+
+#include "KeyTransformation.moc"
diff --git a/src/keys/CompositeKey.h b/src/keys/CompositeKey.h
new file mode 100644
index 000000000..0d7c4a8a1
--- /dev/null
+++ b/src/keys/CompositeKey.h
@@ -0,0 +1,39 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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/>.
+*/
+
+#ifndef KEEPASSX_COMPOSITEKEY_H
+#define KEEPASSX_COMPOSITEKEY_H
+
+#include <QtCore/QList>
+
+#include "Key.h"
+
+class CompositeKey : public Key
+{
+public:
+ ~CompositeKey();
+ CompositeKey* clone() const;
+
+ QByteArray rawKey() const;
+ QByteArray transform(const QByteArray& seed, int rounds) const;
+ void addKey(const Key& key);
+
+private:
+ QList<Key*> m_keys;
+};
+
+#endif // KEEPASSX_COMPOSITEKEY_H
diff --git a/src/keys/Key.h b/src/keys/Key.h
new file mode 100644
index 000000000..b80a6b7ee
--- /dev/null
+++ b/src/keys/Key.h
@@ -0,0 +1,30 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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/>.
+*/
+
+#ifndef KEEPASSX_KEY_H
+#define KEEPASSX_KEY_H
+
+#include <QtCore/QByteArray>
+
+class Key
+{
+public:
+ virtual QByteArray rawKey() const = 0;
+ virtual Key* clone() const = 0;
+};
+
+#endif // KEEPASSX_KEY_H
diff --git a/src/keys/PasswordKey.cpp b/src/keys/PasswordKey.cpp
new file mode 100644
index 000000000..b48e9186a
--- /dev/null
+++ b/src/keys/PasswordKey.cpp
@@ -0,0 +1,35 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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 "PasswordKey.h"
+
+#include "crypto/CryptoHash.h"
+
+QByteArray PasswordKey::rawKey() const
+{
+ return m_key;
+}
+
+void PasswordKey::setPassword(const QString& password)
+{
+ m_key = CryptoHash::hash(password.toUtf8(), CryptoHash::Sha256);
+}
+
+PasswordKey* PasswordKey::clone() const
+{
+ return new PasswordKey(*this);
+}
diff --git a/src/keys/PasswordKey.h b/src/keys/PasswordKey.h
new file mode 100644
index 000000000..259f1c825
--- /dev/null
+++ b/src/keys/PasswordKey.h
@@ -0,0 +1,36 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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/>.
+*/
+
+#ifndef KEEPASSX_PASSWORDKEY_H
+#define KEEPASSX_PASSWORDKEY_H
+
+#include <QtCore/QString>
+
+#include "Key.h"
+
+class PasswordKey : public Key
+{
+public:
+ QByteArray rawKey() const;
+ void setPassword(const QString& password);
+ PasswordKey* clone() const;
+
+private:
+ QByteArray m_key;
+};
+
+#endif // KEEPASSX_PASSWORDKEY_H
diff --git a/src/streams/HashedBlockStream.cpp b/src/streams/HashedBlockStream.cpp
new file mode 100644
index 000000000..a63dba2c4
--- /dev/null
+++ b/src/streams/HashedBlockStream.cpp
@@ -0,0 +1,145 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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 "HashedBlockStream.h"
+
+#include <cstring>
+
+#include "crypto/CryptoHash.h"
+
+const QSysInfo::Endian HashedBlockStream::BYTEORDER = QSysInfo::LittleEndian;
+
+HashedBlockStream::HashedBlockStream(QIODevice* baseDevice)
+ : LayeredStream(baseDevice)
+ , m_blockSize(1024*1024)
+{
+ init();
+}
+
+HashedBlockStream::HashedBlockStream(QIODevice* baseDevice, qint32 blockSize)
+ : LayeredStream(baseDevice)
+ , m_blockSize(blockSize)
+{
+ init();
+}
+
+void HashedBlockStream::init()
+{
+ m_bufferPos = 0;
+ m_blockIndex = 0;
+ m_eof = false;
+}
+
+void HashedBlockStream::close()
+{
+ LayeredStream::close();
+}
+
+qint64 HashedBlockStream::readData(char* data, qint64 maxSize)
+{
+ if (m_eof) {
+ return 0;
+ }
+
+ qint64 bytesRemaining = maxSize;
+ qint64 offset = 0;
+
+ while (bytesRemaining > 0) {
+ if (m_bufferPos == m_buffer.size()) {
+ if (!readHashedBlock()) {
+ return maxSize - bytesRemaining;
+ }
+ }
+
+ int bytesToCopy = qMin(bytesRemaining, static_cast<qint64>(m_buffer.size() - m_bufferPos));
+
+ memcpy(data + offset, m_buffer.constData() + m_bufferPos, bytesToCopy);
+
+ offset += bytesToCopy;
+ m_bufferPos += bytesToCopy;
+ bytesRemaining -= bytesToCopy;
+ }
+
+ return maxSize;
+}
+
+bool HashedBlockStream::readHashedBlock()
+{
+ bool ok;
+
+ quint32 index = Endian::readUInt32(m_baseDevice, BYTEORDER, &ok);
+ if (!ok || index != m_blockIndex) {
+ // TODO error
+ Q_ASSERT(false);
+ return false;
+ }
+
+ QByteArray hash = m_baseDevice->read(32);
+ if (hash.size() != 32) {
+ // TODO error
+ Q_ASSERT(false);
+ return false;
+ }
+
+ m_blockSize = Endian::readInt32(m_baseDevice, BYTEORDER, &ok);
+ if (!ok || m_blockSize < 0) {
+ // TODO error
+ Q_ASSERT(false);
+ return false;
+ }
+
+ if (m_blockSize == 0) {
+ if (hash.count(static_cast<char>(0)) != 32) {
+ // TODO error
+ Q_ASSERT(false);
+ return false;
+ }
+
+ m_eof = true;
+ return false;
+ }
+
+ m_buffer = m_baseDevice->read(m_blockSize);
+ if (m_buffer.size() != m_blockSize) {
+ // TODO error
+ Q_ASSERT(false);
+ return false;
+ }
+
+ if (hash != CryptoHash::hash(m_buffer, CryptoHash::Sha256)) {
+ // TODO error
+ Q_ASSERT(false);
+ return false;
+ }
+
+ m_bufferPos = 0;
+ m_blockIndex++;
+
+ return true;
+}
+
+qint64 HashedBlockStream::writeData(const char* data, qint64 maxSize)
+{
+ // TODO implement
+ return 0;
+}
+
+bool HashedBlockStream::writeHashedBlock()
+{
+ // TODO implement
+ return false;
+}
diff --git a/src/streams/HashedBlockStream.h b/src/streams/HashedBlockStream.h
new file mode 100644
index 000000000..626974878
--- /dev/null
+++ b/src/streams/HashedBlockStream.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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/>.
+*/
+
+#ifndef KEEPASSX_HASHEDBLOCKSTREAM_H
+#define KEEPASSX_HASHEDBLOCKSTREAM_H
+
+#include "LayeredStream.h"
+#include "core/Endian.h"
+#include "crypto/CryptoHash.h"
+
+class HashedBlockStream : public LayeredStream
+{
+ Q_OBJECT
+
+public:
+ explicit HashedBlockStream(QIODevice* baseDevice);
+ HashedBlockStream(QIODevice* baseDevice, qint32 blockSize);
+
+ void close();
+
+protected:
+ qint64 readData(char* data, qint64 maxSize);
+ qint64 writeData(const char* data, qint64 maxSize);
+
+private:
+ void init();
+ bool readHashedBlock();
+ bool writeHashedBlock();
+
+ static const QSysInfo::Endian BYTEORDER;
+ qint32 m_blockSize;
+ QByteArray m_buffer;
+ int m_bufferPos;
+ quint32 m_blockIndex;
+ bool m_eof;
+};
+
+#endif // KEEPASSX_HASHEDBLOCKSTREAM_H
diff --git a/src/streams/LayeredStream.cpp b/src/streams/LayeredStream.cpp
new file mode 100644
index 000000000..dc4dbd828
--- /dev/null
+++ b/src/streams/LayeredStream.cpp
@@ -0,0 +1,72 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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 "LayeredStream.h"
+
+LayeredStream::LayeredStream(QIODevice* baseDevice)
+ : QIODevice(baseDevice)
+ , m_baseDevice(baseDevice)
+{
+ connect(baseDevice, SIGNAL(aboutToClose()), SLOT(closeStream()));
+}
+
+bool LayeredStream::isSequential() const
+{
+ return true;
+}
+
+QString LayeredStream::errorString() const
+{
+ return m_baseDevice->errorString();
+}
+
+bool LayeredStream::open(QIODevice::OpenMode mode)
+{
+ // filter out all other modes
+ mode &= QIODevice::ReadWrite;
+
+ if (mode == QIODevice::ReadWrite) {
+ qWarning("Reading and writing at the same time is not supported.");
+ return false;
+ }
+ else if (openMode() & mode) {
+ return true;
+ }
+ else if (!(m_baseDevice->openMode() & mode)) {
+ qWarning("Base device is not opened correctly.");
+ return false;
+ }
+ else {
+ setOpenMode(mode | QIODevice::Unbuffered);
+ return true;
+ }
+}
+
+qint64 LayeredStream::readData(char* data, qint64 maxSize)
+{
+ return m_baseDevice->read(data, maxSize);
+}
+
+qint64 LayeredStream::writeData(const char* data, qint64 maxSize)
+{
+ return m_baseDevice->write(data, maxSize);
+}
+
+void LayeredStream::closeStream()
+{
+ close();
+}
diff --git a/src/streams/LayeredStream.h b/src/streams/LayeredStream.h
new file mode 100644
index 000000000..86e9d1a6b
--- /dev/null
+++ b/src/streams/LayeredStream.h
@@ -0,0 +1,44 @@
+/*
+* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+*
+* 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/>.
+*/
+
+#ifndef KEEPASSX_LAYEREDSTREAM_H
+#define KEEPASSX_LAYEREDSTREAM_H
+
+#include <QtCore/QIODevice>
+
+class LayeredStream : public QIODevice
+{
+ Q_OBJECT
+
+public:
+ explicit LayeredStream(QIODevice* baseDevice);
+
+ bool isSequential() const;
+ virtual QString errorString() const;
+ bool open(QIODevice::OpenMode mode);
+
+protected:
+ qint64 readData(char* data, qint64 maxSize);
+ qint64 writeData(const char* data, qint64 maxSize);
+
+ QIODevice* m_baseDevice;
+
+private Q_SLOTS:
+ void closeStream();
+};
+
+#endif // KEEPASSX_LAYEREDSTREAM_H
diff --git a/src/streams/SymmetricCipherStream.cpp b/src/streams/SymmetricCipherStream.cpp
new file mode 100644
index 000000000..483abefc3
--- /dev/null
+++ b/src/streams/SymmetricCipherStream.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+ *
+ * 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 "SymmetricCipherStream.h"
+
+SymmetricCipherStream::SymmetricCipherStream(QIODevice* baseDevice, SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
+ SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv)
+ : LayeredStream(baseDevice)
+ , m_bufferPos(0)
+ , m_eof(false)
+{
+ m_cipher = new SymmetricCipher(algo, mode, direction, key, iv);
+}
+
+bool SymmetricCipherStream::reset()
+{
+ m_buffer.clear();
+ m_bufferPos = 0;
+ m_cipher->reset();
+ return true;
+}
+
+qint64 SymmetricCipherStream::readData(char* data, qint64 maxSize)
+{
+ // TODO m_eof is probably wrong and should be removed
+ if (m_eof) {
+ return 0;
+ }
+
+ qint64 bytesRemaining = maxSize;
+ qint64 offset = 0;
+
+ while (bytesRemaining > 0) {
+ if (m_bufferPos == m_buffer.size()) {
+ if (!readBlock()) {
+ return maxSize - bytesRemaining;
+ }
+ }
+
+ int bytesToCopy = qMin(bytesRemaining, static_cast<qint64>(m_buffer.size() - m_bufferPos));
+
+ memcpy(data + offset, m_buffer.constData() + m_bufferPos, bytesToCopy);
+
+ offset += bytesToCopy;
+ m_bufferPos += bytesToCopy;
+ bytesRemaining -= bytesToCopy;
+ }
+
+ return maxSize;
+}
+
+bool SymmetricCipherStream::readBlock()
+{
+ m_buffer = m_baseDevice->read(m_cipher->blockSize());
+
+ if (m_buffer.size() != m_cipher->blockSize()) {
+ m_eof = true;
+ // TODO check if m_buffer.size()!=0
+ return false;
+ }
+ else {
+ m_cipher->processInPlace(m_buffer);
+ m_bufferPos = 0;
+ return true;
+ }
+}
+
+qint64 SymmetricCipherStream::writeData(const char* data, qint64 maxSize)
+{
+ // TODO implement
+ return 0;
+}
+
+bool SymmetricCipherStream::writeBlock()
+{
+ // TODO implement
+ return false;
+}
diff --git a/src/streams/SymmetricCipherStream.h b/src/streams/SymmetricCipherStream.h
new file mode 100644
index 000000000..1891f91c8
--- /dev/null
+++ b/src/streams/SymmetricCipherStream.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
+ *
+ * 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/>.
+ */
+
+#ifndef KEEPASSX_SYMMETRICCIPHERSTREAM_H
+#define KEEPASSX_SYMMETRICCIPHERSTREAM_H
+
+#include <QtCore/QByteArray>
+
+#include "LayeredStream.h"
+#include "crypto/SymmetricCipher.h"
+
+class SymmetricCipherStream : public LayeredStream
+{
+ Q_OBJECT
+
+public:
+ SymmetricCipherStream(QIODevice* baseDevice, SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
+ SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv);
+ bool reset();
+
+protected:
+ qint64 readData(char* data, qint64 maxSize);
+ qint64 writeData(const char* data, qint64 maxSize);
+
+private:
+ bool readBlock();
+ bool writeBlock();
+
+ SymmetricCipher* m_cipher;
+ QByteArray m_buffer;
+ int m_bufferPos;
+ bool m_eof;
+};
+
+#endif // KEEPASSX_SYMMETRICCIPHERSTREAM_H