Skip to content

Commit 180c1af

Browse files
committed
Added keyfiles
1 parent b178051 commit 180c1af

File tree

6 files changed

+297
-76
lines changed

6 files changed

+297
-76
lines changed

include/encryptionengine.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ class EncryptionEngine
2525

2626
bool isHardwareAccelerationSupported() const;
2727

28-
QByteArray deriveKey(const QString &password, const QString &salt, const QString &kdf, int iterations, int keySize);
28+
QByteArray deriveKey(const QString& password, const QByteArray& salt, const QStringList& keyfilePaths, const QString& kdf, int iterations);
29+
QByteArray deriveKeyWithoutKeyfile(const QString &password, const QString &salt, const QString &kdf, int iterations, int keySize);
2930

3031
void runBenchmark();
3132
void benchmarkCipher(const QString& algorithm, const QString& kdf, bool useHardwareAcceleration);
@@ -43,9 +44,9 @@ class EncryptionEngine
4344
bool performAuthenticatedDecryption(EVP_CIPHER_CTX* ctx, const EVP_CIPHER* cipher, const QByteArray& key, const QByteArray& iv, QFile& inputFile, QFile& outputFile);
4445
QByteArray performKeyDerivation(const QByteArray& passwordWithKeyfile, const QByteArray& salt, const QString& kdf, int iterations, int keySize);
4546

46-
QByteArray deriveKey(const QString& password, const QByteArray& salt, const QStringList& keyfilePaths, const QString& kdf, int iterations);
4747
QByteArray readKeyfile(const QString& keyfilePath);
4848

49+
4950
bool checkHardwareSupport();
5051
};
5152

src/encryptionengine_crypto.cpp

Lines changed: 107 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,58 @@
33
#include <QDebug>
44
#include <openssl/rand.h>
55
#include <openssl/evp.h>
6-
#include <sodium.h> // Ensure Sodium library is included
6+
#include <sodium.h>
77

88
bool EncryptionEngine::cryptOperation(const QString& inputPath, const QString& outputPath, const QString& password, const QString& algorithm, bool encrypt, const QString& kdf, int iterations, bool useHMAC, const QString& customHeader, const QStringList& keyfilePaths) {
9+
qDebug() << "Starting cryptOperation...";
10+
qDebug() << "Encrypt mode:" << encrypt;
11+
qDebug() << "Input file:" << inputPath;
12+
qDebug() << "Output file:" << outputPath;
13+
qDebug() << "Algorithm:" << algorithm;
14+
qDebug() << "KDF:" << kdf;
15+
qDebug() << "Iterations:" << iterations;
16+
qDebug() << "Use HMAC:" << useHMAC;
17+
918
QFile inputFile(inputPath);
1019
QFile outputFile(outputPath);
1120

1221
if (!inputFile.open(QIODevice::ReadOnly)) {
13-
qDebug() << "Failed to open input file";
22+
qDebug() << "Failed to open input file:" << inputPath;
1423
return false;
1524
}
1625

1726
if (!outputFile.open(QIODevice::WriteOnly)) {
18-
qDebug() << "Failed to open output file";
27+
qDebug() << "Failed to open output file:" << outputPath;
1928
return false;
2029
}
2130

2231
const EVP_CIPHER* cipher = getCipher(algorithm);
2332
if (!cipher) {
24-
qDebug() << "Invalid algorithm";
33+
qDebug() << "Invalid algorithm:" << algorithm;
2534
return false;
2635
}
2736

2837
int ivLength = EVP_CIPHER_iv_length(cipher);
2938
QByteArray iv(ivLength, 0);
30-
QByteArray salt(16, 0);
39+
QByteArray salt(32, 0);
3140

3241
if (encrypt) {
33-
RAND_bytes(reinterpret_cast<unsigned char*>(iv.data()), ivLength);
3442
RAND_bytes(reinterpret_cast<unsigned char*>(salt.data()), salt.size());
35-
outputFile.write(customHeader.toUtf8());
36-
outputFile.write(salt);
37-
outputFile.write(iv);
38-
lastIv = iv; // Store the last used IV
43+
RAND_bytes(reinterpret_cast<unsigned char*>(iv.data()), ivLength);
3944
} else {
40-
QByteArray header(customHeader.size(), 0);
41-
if (inputFile.read(header.data(), customHeader.size()) != customHeader.size() || header != customHeader.toUtf8()) {
42-
qDebug() << "Failed to read or validate custom header";
45+
inputFile.seek(customHeader.size()); // Skip the custom header
46+
if (inputFile.read(salt.data(), salt.size()) != salt.size()) {
47+
qDebug() << "Failed to read salt from input file";
48+
inputFile.close();
4349
return false;
4450
}
45-
inputFile.read(salt.data(), salt.size());
46-
inputFile.read(iv.data(), iv.size());
47-
lastIv = iv; // Store the last used IV
4851
}
4952

53+
qDebug() << "Deriving key...";
5054
QByteArray key = deriveKey(password, salt, keyfilePaths, kdf, iterations);
5155

5256
if (key.isEmpty()) {
57+
qDebug() << "Key derivation failed.";
5358
return false;
5459
}
5560

@@ -66,14 +71,29 @@ bool EncryptionEngine::cryptOperation(const QString& inputPath, const QString& o
6671
}
6772

6873
bool success = false;
74+
6975
if (encrypt) {
76+
outputFile.write(customHeader.toUtf8());
77+
outputFile.write(salt);
78+
outputFile.write(iv);
7079
success = useHMAC ? performAuthenticatedEncryption(ctx, cipher, key, iv, inputFile, outputFile)
7180
: performStandardEncryption(ctx, cipher, key, iv, inputFile, outputFile);
7281
} else {
82+
QByteArray header(customHeader.size(), 0);
83+
if (inputFile.read(header.data(), customHeader.size()) != customHeader.size() || header != customHeader.toUtf8()) {
84+
qDebug() << "Failed to read or validate custom header";
85+
return false;
86+
}
87+
inputFile.seek(customHeader.size() + salt.size()); // Skip header and salt
88+
inputFile.read(iv.data(), iv.size());
7389
success = useHMAC ? performAuthenticatedDecryption(ctx, cipher, key, iv, inputFile, outputFile)
7490
: performStandardDecryption(ctx, cipher, key, iv, inputFile, outputFile);
7591
}
7692

93+
if (!success) {
94+
qDebug() << "Encryption/Decryption process failed.";
95+
}
96+
7797
EVP_CIPHER_CTX_free(ctx);
7898
inputFile.close();
7999
outputFile.close();
@@ -87,34 +107,41 @@ bool EncryptionEngine::cryptOperation(const QString& inputPath, const QString& o
87107
}
88108

89109
bool EncryptionEngine::performStandardEncryption(EVP_CIPHER_CTX* ctx, const EVP_CIPHER* cipher, const QByteArray& key, const QByteArray& iv, QFile& inputFile, QFile& outputFile) {
90-
if (!EVP_EncryptInit_ex(ctx, cipher, nullptr, reinterpret_cast<const unsigned char*>(key.data()), reinterpret_cast<const unsigned char*>(iv.data()))) {
110+
// Initialize encryption operation
111+
if (1 != EVP_EncryptInit_ex(ctx, cipher, nullptr, reinterpret_cast<const unsigned char*>(key.data()), reinterpret_cast<const unsigned char*>(iv.data()))) {
91112
qDebug() << "EVP_EncryptInit_ex failed";
92113
return false;
93114
}
94115

95116
QByteArray buffer(4096, 0);
96-
QByteArray outputBuffer(4096 + EVP_CIPHER_block_size(cipher), 0);
97-
int outLen;
98-
117+
QByteArray outBuf(4096 + EVP_CIPHER_block_size(cipher), 0);
118+
int outLen = 0;
119+
99120
while (!inputFile.atEnd()) {
100121
int inLen = inputFile.read(buffer.data(), buffer.size());
101-
if (!EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen, reinterpret_cast<unsigned char*>(buffer.data()), inLen)) {
122+
if (1 != EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(outBuf.data()), &outLen, reinterpret_cast<const unsigned char*>(buffer.data()), inLen)) {
102123
qDebug() << "EVP_EncryptUpdate failed";
103124
return false;
104125
}
105-
outputFile.write(outputBuffer.data(), outLen);
126+
outputFile.write(outBuf.data(), outLen);
106127
}
107128

108-
if (!EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen)) {
129+
// Finalize encryption
130+
if (1 != EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(outBuf.data()), &outLen)) {
109131
qDebug() << "EVP_EncryptFinal_ex failed";
110132
return false;
111133
}
112-
outputFile.write(outputBuffer.data(), outLen);
134+
outputFile.write(outBuf.data(), outLen);
113135

114136
return true;
115137
}
116138

117139
bool EncryptionEngine::performStandardDecryption(EVP_CIPHER_CTX* ctx, const EVP_CIPHER* cipher, const QByteArray& key, const QByteArray& iv, QFile& inputFile, QFile& outputFile) {
140+
qDebug() << "Starting decryption process...";
141+
qDebug() << "Key (Hex):" << key.toHex();
142+
qDebug() << "IV (Hex):" << iv.toHex();
143+
144+
// Initialize the decryption operation
118145
if (!EVP_DecryptInit_ex(ctx, cipher, nullptr, reinterpret_cast<const unsigned char*>(key.data()), reinterpret_cast<const unsigned char*>(iv.data()))) {
119146
qDebug() << "EVP_DecryptInit_ex failed";
120147
return false;
@@ -143,74 +170,106 @@ bool EncryptionEngine::performStandardDecryption(EVP_CIPHER_CTX* ctx, const EVP_
143170
}
144171

145172
bool EncryptionEngine::performAuthenticatedEncryption(EVP_CIPHER_CTX* ctx, const EVP_CIPHER* cipher, const QByteArray& key, const QByteArray& iv, QFile& inputFile, QFile& outputFile) {
146-
QByteArray tag(16, 0);
173+
QByteArray tag(16, 0); // GCM mode requires a 16-byte tag
174+
175+
// Initialize encryption operation
147176
if (!EVP_EncryptInit_ex(ctx, cipher, nullptr, reinterpret_cast<const unsigned char*>(key.data()), reinterpret_cast<const unsigned char*>(iv.data()))) {
148177
qDebug() << "EVP_EncryptInit_ex failed";
149178
return false;
150179
}
151180

152-
QByteArray buffer(4096, 0);
153-
QByteArray outputBuffer(4096 + EVP_CIPHER_block_size(cipher), 0);
154-
int outLen;
181+
QByteArray buffer(4096, 0); // Input buffer
182+
QByteArray outputBuffer; // Output buffer
155183

184+
// Encrypt the data in chunks
156185
while (!inputFile.atEnd()) {
157-
int inLen = inputFile.read(buffer.data(), buffer.size());
158-
if (!EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen, reinterpret_cast<unsigned char*>(buffer.data()), inLen)) {
186+
qint64 bytesRead = inputFile.read(buffer.data(), buffer.size());
187+
if (bytesRead <= 0) break;
188+
189+
outputBuffer.resize(bytesRead + EVP_CIPHER_block_size(cipher));
190+
int outLen;
191+
192+
if (!EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen,
193+
reinterpret_cast<const unsigned char*>(buffer.constData()), bytesRead)) {
159194
qDebug() << "EVP_EncryptUpdate failed";
160195
return false;
161196
}
162-
outputFile.write(outputBuffer.data(), outLen);
197+
198+
outputFile.write(outputBuffer.constData(), outLen);
163199
}
164200

201+
// Finalize the encryption
202+
outputBuffer.resize(EVP_CIPHER_block_size(cipher));
203+
int outLen;
165204
if (!EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen)) {
166205
qDebug() << "EVP_EncryptFinal_ex failed";
167206
return false;
168207
}
169-
outputFile.write(outputBuffer.data(), outLen);
170208

209+
if (outLen > 0) {
210+
outputFile.write(outputBuffer.constData(), outLen);
211+
}
212+
213+
// Get the tag
171214
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag.size(), tag.data())) {
172215
qDebug() << "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_GET_TAG) failed";
173216
return false;
174217
}
218+
219+
// Append the tag to the end of the file
175220
outputFile.write(tag);
176221

177222
return true;
178223
}
179224

180225
bool EncryptionEngine::performAuthenticatedDecryption(EVP_CIPHER_CTX* ctx, const EVP_CIPHER* cipher, const QByteArray& key, const QByteArray& iv, QFile& inputFile, QFile& outputFile) {
181-
QByteArray tag(16, 0);
182-
inputFile.seek(inputFile.size() - tag.size());
183-
inputFile.read(tag.data(), tag.size());
184-
inputFile.seek(0);
226+
QByteArray tag(16, 0); // GCM mode requires a 16-byte tag
227+
228+
// Read the entire encrypted content
229+
QByteArray encryptedContent = inputFile.readAll();
230+
231+
// The last 16 bytes should be the tag
232+
if (encryptedContent.size() < 16) {
233+
qDebug() << "Encrypted content is too short";
234+
return false;
235+
}
185236

237+
tag = encryptedContent.right(16);
238+
encryptedContent.chop(16); // Remove the tag from the encrypted content
239+
240+
qDebug() << "Tag read for decryption (Hex):" << tag.toHex();
241+
242+
// Initialize decryption operation
186243
if (!EVP_DecryptInit_ex(ctx, cipher, nullptr, reinterpret_cast<const unsigned char*>(key.data()), reinterpret_cast<const unsigned char*>(iv.data()))) {
187244
qDebug() << "EVP_DecryptInit_ex failed";
188245
return false;
189246
}
190247

191-
QByteArray buffer(4096, 0);
192-
QByteArray outputBuffer(4096 + EVP_CIPHER_block_size(cipher), 0);
248+
QByteArray outputBuffer(encryptedContent.size() + EVP_CIPHER_block_size(cipher), 0);
193249
int outLen;
194250

195-
while (inputFile.pos() < inputFile.size() - tag.size()) {
196-
int inLen = inputFile.read(buffer.data(), buffer.size());
197-
if (!EVP_DecryptUpdate(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen, reinterpret_cast<unsigned char*>(buffer.data()), inLen)) {
198-
qDebug() << "EVP_DecryptUpdate failed";
199-
return false;
200-
}
201-
outputFile.write(outputBuffer.data(), outLen);
251+
// Decrypt the data
252+
if (!EVP_DecryptUpdate(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen,
253+
reinterpret_cast<const unsigned char*>(encryptedContent.constData()), encryptedContent.size())) {
254+
qDebug() << "EVP_DecryptUpdate failed";
255+
return false;
202256
}
203257

258+
// Set the expected tag
204259
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size(), tag.data())) {
205260
qDebug() << "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_TAG) failed";
206261
return false;
207262
}
208263

209-
if (!EVP_DecryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()), &outLen)) {
210-
qDebug() << "EVP_DecryptFinal_ex failed";
264+
int tmpLen;
265+
// Finalize the decryption and check the tag
266+
if (!EVP_DecryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(outputBuffer.data()) + outLen, &tmpLen)) {
267+
qDebug() << "EVP_DecryptFinal_ex failed - authentication failure";
211268
return false;
212269
}
213-
outputFile.write(outputBuffer.data(), outLen);
270+
271+
outLen += tmpLen;
272+
outputFile.write(outputBuffer.constData(), outLen);
214273

215274
return true;
216275
}

src/encryptionengine_fileops.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <QFile>
33
#include <QProcess>
44
#include <QDebug>
5+
#include <openssl/rand.h>
56

67
bool EncryptionEngine::compressFolder(const QString& folderPath, const QString& outputFilePath) {
78
QProcess process;
@@ -43,4 +44,4 @@ bool EncryptionEngine::decryptFolder(const QString& folderPath, const QString& p
4344
return false;
4445
}
4546
return decompressFolder(compressedFilePath, folderPath);
46-
}
47+
}

0 commit comments

Comments
 (0)