-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathqfileencrypted.h
97 lines (80 loc) · 3.14 KB
/
qfileencrypted.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* This file is part of PasswordSender.
*
* PasswordSender 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 3 of the License, or
* (at your option) any later version.
* PasswordSender 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 PasswordSender. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright 2020 Wiebe Cazemier <wiebe@halfgaar.net>
*/
#ifndef QFILEENCRYPTED_H
#define QFILEENCRYPTED_H
#include <QObject>
#include <QFile>
#include <openssl/evp.h>
#include <openssl/err.h>
/**
* @brief The QFileEncrypted class can act as a drop in replacement for QFile, or any QIODevice, but then with encryption, using AES256.
*
* There are some caveats. Encryption requires padding to align blocks with the encryption key. Data is retained in buffers so we write
* to disk with the proper padding size. This padding is writting to disk on close, and it's read on object instantiation. All this
* makes it hard to implement a class that supports reading and writing at the same time.
*
* Seeking is not tested, and will probably not work. I have some ideas how to implement it, but I didn't need it so far, so I
* haven't... At then, it's probably only doable for reading.
*/
class QFileEncrypted : public QFile
{
Q_OBJECT
Q_DISABLE_COPY(QFileEncrypted)
EVP_CIPHER_CTX *writeCipherContext;
EVP_CIPHER_CTX *readCipherContext;
QByteArray cipherKey;
QByteArray iv;
int cryptBlockSize;
char *writeCirBuf = nullptr;
qint64 writeBufWPos = 0;
qint64 writeBufRPos = 0;
char *writeCryptBufferIn = nullptr;
char *writeCryptBufferOut = nullptr;
qint64 writeCryptBufferSize = 0;
char *readCirBuf = nullptr;
qint64 readBufWPos = 0;
qint64 readBufRPos = 0;
char *readCryptBufferIn = nullptr;
char *readCryptBufferOut = nullptr;
qint64 readCryptBufferSize = 0;
qint64 decryptedSize = 0;
int paddingSize = -1;
void resizeWriteCryptBuffer(qint64 size);
void resizeReadCryptBuffer(qint64 size);
void setPaddingSize();
qint64 getWriteBufUsedBytes() const;
qint64 getReadBufUsedBytes() const;
protected:
qint64 readData(char *data, qint64 maxSize) override;
qint64 writeData(const char *data, qint64 maxSize) override;
void throwError[[noreturn]]() const
{
unsigned long error = ERR_get_error();
QByteArray r(128, 0);
ERR_error_string(error, r.data());
throw std::runtime_error(r.toStdString());
}
public:
QFileEncrypted(const QString &name, const QByteArray &iv, const QByteArray &cipherKey, QObject *parent = nullptr);
~QFileEncrypted() override;
void close() override;
qint64 size() const override;
bool atEnd() const override;
bool open(QIODevice::OpenMode mode) override;
};
#endif // QFILEENCRYPTED_H