Implement writing to the SymmetricCipherStream.

This commit is contained in:
Felix Geyer 2010-09-16 18:20:46 +02:00
parent 49d64d8162
commit c2bdfab158
3 changed files with 101 additions and 14 deletions

View file

@ -21,7 +21,8 @@ SymmetricCipherStream::SymmetricCipherStream(QIODevice* baseDevice, SymmetricCip
SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv) SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv)
: LayeredStream(baseDevice) : LayeredStream(baseDevice)
, m_bufferPos(0) , m_bufferPos(0)
, m_eof(false) , m_bufferFilling(false)
, m_error(false)
{ {
m_cipher = new SymmetricCipher(algo, mode, direction, key, iv); m_cipher = new SymmetricCipher(algo, mode, direction, key, iv);
} }
@ -30,22 +31,30 @@ bool SymmetricCipherStream::reset()
{ {
m_buffer.clear(); m_buffer.clear();
m_bufferPos = 0; m_bufferPos = 0;
m_bufferFilling = false;
m_error = false;
m_cipher->reset(); m_cipher->reset();
return true; return true;
} }
void SymmetricCipherStream::close()
{
if (isWritable()) {
writeBlock();
}
LayeredStream::close();
}
qint64 SymmetricCipherStream::readData(char* data, qint64 maxSize) qint64 SymmetricCipherStream::readData(char* data, qint64 maxSize)
{ {
// TODO m_eof is probably wrong and should be removed Q_ASSERT(maxSize >= 0);
if (m_eof) {
return 0;
}
qint64 bytesRemaining = maxSize; qint64 bytesRemaining = maxSize;
qint64 offset = 0; qint64 offset = 0;
while (bytesRemaining > 0) { while (bytesRemaining > 0) {
if (m_bufferPos == m_buffer.size()) { if ((m_bufferPos == m_buffer.size()) || m_bufferFilling) {
if (!readBlock()) { if (!readBlock()) {
return maxSize - bytesRemaining; return maxSize - bytesRemaining;
} }
@ -65,28 +74,80 @@ qint64 SymmetricCipherStream::readData(char* data, qint64 maxSize)
bool SymmetricCipherStream::readBlock() bool SymmetricCipherStream::readBlock()
{ {
if (m_bufferFilling) {
m_buffer.append(m_baseDevice->read(m_cipher->blockSize() - m_buffer.size()));
}
else {
m_buffer = m_baseDevice->read(m_cipher->blockSize()); m_buffer = m_baseDevice->read(m_cipher->blockSize());
}
if (m_buffer.size() != m_cipher->blockSize()) { if (m_buffer.size() != m_cipher->blockSize()) {
m_eof = true; m_bufferFilling = true;
// TODO check if m_buffer.size()!=0
return false; return false;
} }
else { else {
m_cipher->processInPlace(m_buffer); m_cipher->processInPlace(m_buffer);
m_bufferPos = 0; m_bufferPos = 0;
m_bufferFilling = false;
return true; return true;
} }
} }
qint64 SymmetricCipherStream::writeData(const char* data, qint64 maxSize) qint64 SymmetricCipherStream::writeData(const char* data, qint64 maxSize)
{ {
// TODO implement Q_ASSERT(maxSize >= 0);
if (m_error) {
return 0; return 0;
} }
qint64 bytesRemaining = maxSize;
qint64 offset = 0;
while (bytesRemaining > 0) {
int bytesToCopy = qMin(bytesRemaining, static_cast<qint64>(m_cipher->blockSize() - m_buffer.size()));
m_buffer.append(data + offset, bytesToCopy);
offset += bytesToCopy;
bytesRemaining -= bytesToCopy;
if (m_buffer.size() == m_cipher->blockSize()) {
if (!writeBlock()) {
if (m_error) {
return -1;
}
else {
return maxSize - bytesRemaining;
}
}
}
}
return maxSize;
}
bool SymmetricCipherStream::writeBlock() bool SymmetricCipherStream::writeBlock()
{ {
// TODO implement if (m_buffer.isEmpty()) {
return true;
}
else if (m_buffer.size() != m_cipher->blockSize()) {
int padLen = m_cipher->blockSize() - m_buffer.size();
for (int i=m_buffer.size(); i<m_cipher->blockSize(); i++) {
m_buffer.append(static_cast<char>(padLen));
}
}
m_cipher->processInPlace(m_buffer);
if (m_baseDevice->write(m_buffer) != m_buffer.size()) {
m_error = true;
// TODO copy error string
return false; return false;
} }
else {
m_buffer.clear();
return true;
}
}

View file

@ -31,6 +31,7 @@ public:
SymmetricCipherStream(QIODevice* baseDevice, SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipherStream(QIODevice* baseDevice, SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv); SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv);
bool reset(); bool reset();
void close();
protected: protected:
qint64 readData(char* data, qint64 maxSize); qint64 readData(char* data, qint64 maxSize);
@ -43,7 +44,8 @@ private:
SymmetricCipher* m_cipher; SymmetricCipher* m_cipher;
QByteArray m_buffer; QByteArray m_buffer;
int m_bufferPos; int m_bufferPos;
bool m_eof; bool m_bufferFilling;
bool m_error;
}; };
#endif // KEEPASSX_SYMMETRICCIPHERSTREAM_H #endif // KEEPASSX_SYMMETRICCIPHERSTREAM_H

View file

@ -53,6 +53,30 @@ void TestSymmetricCipher::testAes256CbcEncryption()
QCOMPARE(QString(cipher.process(plainText).toHex()), QCOMPARE(QString(cipher.process(plainText).toHex()),
QString(cipherText.toHex())); QString(cipherText.toHex()));
QBuffer buffer;
SymmetricCipherStream stream(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt, key, iv);
buffer.open(QIODevice::WriteOnly);
stream.open(QIODevice::WriteOnly);
buffer.reset();
buffer.buffer().clear();
stream.reset();
stream.write(plainText.left(16));
QCOMPARE(QString(buffer.data().toHex()), QString(cipherText.left(16).toHex()));
buffer.reset();
buffer.buffer().clear();
stream.reset();
stream.write(plainText.left(10));
QCOMPARE(QString(buffer.data().toHex()), QString());
buffer.reset();
buffer.buffer().clear();
stream.reset();
stream.write(plainText.left(10));
stream.close();
QCOMPARE(buffer.data().size(), 16);
} }
void TestSymmetricCipher::testAes256CbcDecryption() void TestSymmetricCipher::testAes256CbcDecryption()