diff options
author | Felix Geyer <debfx@fobos.de> | 2010-09-18 19:19:42 +0400 |
---|---|---|
committer | Felix Geyer <debfx@fobos.de> | 2010-09-18 19:19:42 +0400 |
commit | 5da7d3fca6647c8a67c5d6a1d057ca0367bf9d4b (patch) | |
tree | 67a166e69ba159956356e40dc7b73851c8d94635 /src | |
parent | c93ac9f6fc860389c7e1dcfd3c0167e507d3bfd9 (diff) |
Implement writing in SymmetricCipherStream and add a unit test.
Diffstat (limited to 'src')
-rw-r--r-- | src/core/Endian.cpp | 66 | ||||
-rw-r--r-- | src/core/Endian.h | 8 | ||||
-rw-r--r-- | src/streams/HashedBlockStream.cpp | 104 | ||||
-rw-r--r-- | src/streams/HashedBlockStream.h | 6 |
4 files changed, 178 insertions, 6 deletions
diff --git a/src/core/Endian.cpp b/src/core/Endian.cpp index 8fca50f12..177c3a7fb 100644 --- a/src/core/Endian.cpp +++ b/src/core/Endian.cpp @@ -131,4 +131,70 @@ quint64 readUInt64(QIODevice* device, QSysInfo::Endian byteOrder, bool* ok) return readInt64(device, byteOrder, ok); } +QByteArray int16ToBytes(qint16 num, QSysInfo::Endian byteOrder) +{ + QByteArray ba; + ba.resize(2); + + if (byteOrder == QSysInfo::LittleEndian) { + qToLittleEndian<qint16>(num, reinterpret_cast<uchar*>(ba.data())); + } + else { + qToBigEndian<qint64>(num, reinterpret_cast<uchar*>(ba.data())); + } + + return ba; +} + +QByteArray int32ToBytes(qint32 num, QSysInfo::Endian byteOrder) +{ + QByteArray ba; + ba.resize(4); + + if (byteOrder == QSysInfo::LittleEndian) { + qToLittleEndian<qint32>(num, reinterpret_cast<uchar*>(ba.data())); + } + else { + qToBigEndian<qint32>(num, reinterpret_cast<uchar*>(ba.data())); + } + + return ba; +} + +QByteArray int64ToBytes(qint64 num, QSysInfo::Endian byteOrder) +{ + QByteArray ba; + ba.resize(8); + + if (byteOrder == QSysInfo::LittleEndian) { + qToLittleEndian<qint64>(num, reinterpret_cast<uchar*>(ba.data())); + } + else { + qToBigEndian<qint64>(num, reinterpret_cast<uchar*>(ba.data())); + } + + return ba; +} + +bool writeInt16(qint16 num, QIODevice* device, QSysInfo::Endian byteOrder) +{ + QByteArray ba = int16ToBytes(num, byteOrder); + int bytesWritten = device->write(ba); + return (bytesWritten == ba.size()); +} + +bool writeInt32(qint32 num, QIODevice* device, QSysInfo::Endian byteOrder) +{ + QByteArray ba = int32ToBytes(num, byteOrder); + int bytesWritten = device->write(ba); + return (bytesWritten == ba.size()); +} + +bool writeInt64(qint64 num, QIODevice* device, QSysInfo::Endian byteOrder) +{ + QByteArray ba = int64ToBytes(num, byteOrder); + int bytesWritten = device->write(ba); + return (bytesWritten == ba.size()); +} + } // namespace Endian diff --git a/src/core/Endian.h b/src/core/Endian.h index 8958cc400..023df6463 100644 --- a/src/core/Endian.h +++ b/src/core/Endian.h @@ -38,6 +38,14 @@ namespace Endian 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); + + QByteArray int16ToBytes(qint16 num, QSysInfo::Endian byteOrder); + QByteArray int32ToBytes(qint32 num, QSysInfo::Endian byteOrder); + QByteArray int64ToBytes(qint64 num, QSysInfo::Endian byteOrder); + + bool writeInt16(qint16 num, QIODevice* device, QSysInfo::Endian byteOrder); + bool writeInt32(qint32 num, QIODevice* device, QSysInfo::Endian byteOrder); + bool writeInt64(qint64 num, QIODevice* device, QSysInfo::Endian byteOrder); }; #endif // KEEPASSX_ENDIAN_H diff --git a/src/streams/HashedBlockStream.cpp b/src/streams/HashedBlockStream.cpp index a63dba2c4..c758fc4e9 100644 --- a/src/streams/HashedBlockStream.cpp +++ b/src/streams/HashedBlockStream.cpp @@ -19,6 +19,7 @@ #include <cstring> +#include "core/Endian.h" #include "crypto/CryptoHash.h" const QSysInfo::Endian HashedBlockStream::BYTEORDER = QSysInfo::LittleEndian; @@ -42,10 +43,41 @@ void HashedBlockStream::init() m_bufferPos = 0; m_blockIndex = 0; m_eof = false; + m_error = false; +} + +bool HashedBlockStream::reset() +{ + if (isWritable()) { + if (!m_buffer.isEmpty()) { + if (!writeHashedBlock()) { + return false; + } + } + + // write empty final block + if (!writeHashedBlock()) { + return false; + } + } + + init(); + m_buffer.clear(); + + return true; } void HashedBlockStream::close() { + if (isWritable()) { + if (!m_buffer.isEmpty()) { + writeHashedBlock(); + } + + // write empty final block + writeHashedBlock(); + } + LayeredStream::close(); } @@ -134,12 +166,76 @@ bool HashedBlockStream::readHashedBlock() qint64 HashedBlockStream::writeData(const char* data, qint64 maxSize) { - // TODO implement - return 0; + Q_ASSERT(maxSize >= 0); + + if (m_error) { + return 0; + } + + qint64 bytesRemaining = maxSize; + qint64 offset = 0; + + while (bytesRemaining > 0) { + int bytesToCopy = qMin(bytesRemaining, static_cast<qint64>(m_blockSize - m_buffer.size())); + + m_buffer.append(data + offset, bytesToCopy); + + offset += bytesToCopy; + bytesRemaining -= bytesToCopy; + + if (m_buffer.size() == m_blockSize) { + if (!writeHashedBlock()) { + if (m_error) { + return -1; + } + else { + return maxSize - bytesRemaining; + } + } + } + } + + return maxSize; } bool HashedBlockStream::writeHashedBlock() { - // TODO implement - return false; + if (!Endian::writeInt32(m_blockIndex, m_baseDevice, BYTEORDER)) { + // TODO error + Q_ASSERT(false); + return false; + } + m_blockIndex++; + + QByteArray hash; + if (!m_buffer.isEmpty()) { + hash = CryptoHash::hash(m_buffer, CryptoHash::Sha256); + } + else { + hash.fill(0, 32); + } + + if (m_baseDevice->write(hash) != hash.size()) { + // TODO error + Q_ASSERT(false); + return false; + } + + if (!Endian::writeInt32(m_buffer.size(), m_baseDevice, BYTEORDER)) { + // TODO error + Q_ASSERT(false); + return false; + } + + if (!m_buffer.isEmpty()) { + if (m_baseDevice->write(m_buffer) != m_buffer.size()) { + // TODO error + Q_ASSERT(false); + return false; + } + + m_buffer.clear(); + } + + return true; } diff --git a/src/streams/HashedBlockStream.h b/src/streams/HashedBlockStream.h index 626974878..3aa23bf22 100644 --- a/src/streams/HashedBlockStream.h +++ b/src/streams/HashedBlockStream.h @@ -18,9 +18,9 @@ #ifndef KEEPASSX_HASHEDBLOCKSTREAM_H #define KEEPASSX_HASHEDBLOCKSTREAM_H +#include <QtCore/QSysInfo> + #include "LayeredStream.h" -#include "core/Endian.h" -#include "crypto/CryptoHash.h" class HashedBlockStream : public LayeredStream { @@ -30,6 +30,7 @@ public: explicit HashedBlockStream(QIODevice* baseDevice); HashedBlockStream(QIODevice* baseDevice, qint32 blockSize); + bool reset(); void close(); protected: @@ -47,6 +48,7 @@ private: int m_bufferPos; quint32 m_blockIndex; bool m_eof; + bool m_error; }; #endif // KEEPASSX_HASHEDBLOCKSTREAM_H |