24#include <openssl/aes.h>
25#include <openssl/rand.h>
26#include <openssl/sha.h>
28#include <QCryptographicHash>
41 m_encodeCTX = EVP_CIPHER_CTX_new();
42 m_decodeCTX = EVP_CIPHER_CTX_new();
43 EVP_CIPHER_CTX_init(m_encodeCTX);
44 EVP_CIPHER_CTX_init(m_decodeCTX);
49 EVP_CIPHER_CTX_cleanup(m_encodeCTX);
50 EVP_CIPHER_CTX_cleanup(m_decodeCTX);
51 EVP_CIPHER_CTX_free(m_encodeCTX);
52 EVP_CIPHER_CTX_free(m_decodeCTX);
63bool AesInterface::init(
int evpMode,
const QByteArray &password,
const QByteArray &iVector)
68 const int nrounds = 5;
69 uchar key[EVP_MAX_KEY_LENGTH];
74 i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(),
nullptr, (uchar*)password.data(), password.size(), nrounds, key,
nullptr);
77 qWarning(
"Key size is %d bits - should be 256 bits",
i * 8);
82 if (evpMode == EVP_PKEY_MO_ENCRYPT) {
84 result = EVP_EncryptInit_ex(m_encodeCTX, EVP_aes_256_cbc(), NULL, key, (uchar*)m_iVector.constData());
86 else if (evpMode == EVP_PKEY_MO_DECRYPT) {
87 result = EVP_DecryptInit_ex(m_decodeCTX, EVP_aes_256_cbc(), NULL, key, (uchar*)iVector.constData());
91 qWarning(
"EVP is not initialized!");
100 if (!init(EVP_PKEY_MO_ENCRYPT, password)) {
106 int dataLength = plainData.size();
107 int cipherlength = dataLength + AES_BLOCK_SIZE;
109 auto* ciphertext = (uchar*)malloc(cipherlength);
112 EVP_EncryptInit_ex(m_encodeCTX, NULL, NULL, NULL, NULL);
116 EVP_EncryptUpdate(m_encodeCTX, ciphertext, &cipherlength, (uchar*)plainData.data(), dataLength);
119 EVP_EncryptFinal_ex(m_encodeCTX, ciphertext + cipherlength, &finalLength);
121 dataLength = cipherlength + finalLength;
122 QByteArray out((
char*)ciphertext, dataLength);
134 if (cipherData.isEmpty()) {
139 QList<QByteArray> cipherSections(cipherData.split(
'$'));
140 if (cipherSections.size() != 3) {
141 qWarning() <<
"Decrypt error: It seems data is corrupted";
146 QMessageBox::information(
nullptr, tr(
"Warning!"), tr(
"Data has been encrypted with a newer version of Falkon."
147 "\nPlease install latest version of Falkon."));
151 if (cipherSections.at(0).toInt() != 1) {
152 qWarning() << Q_FUNC_INFO <<
"There is just version 1 of decoder, yet ;-)";
156 if (!init(EVP_PKEY_MO_DECRYPT, password, QByteArray::fromBase64(cipherSections.at(1)))) {
160 QByteArray cipherArray = QByteArray::fromBase64(cipherSections.at(2));
161 int cipherLength = cipherArray.size();
162 int plainTextLength = cipherLength;
165 auto* cipherText = (uchar*)cipherArray.data();
167 auto* plainText = (uchar*)malloc(plainTextLength + AES_BLOCK_SIZE);
169 EVP_DecryptInit_ex(m_decodeCTX, NULL, NULL, NULL, NULL);
170 EVP_DecryptUpdate(m_decodeCTX, plainText, &plainTextLength, cipherText, cipherLength);
171 int success = EVP_DecryptFinal_ex(m_decodeCTX, plainText + plainTextLength, &finalLength);
173 cipherLength = plainTextLength + finalLength;
175 QByteArray result((
char*)plainText, cipherLength);
188 if (!masterPassword.isEmpty()) {
189 QByteArray result = masterPassword.toUtf8();
190 result = QCryptographicHash::hash(result, QCryptographicHash::Sha1) + result;
191 result = QCryptographicHash::hash(result, QCryptographicHash::Sha1);
192 return result.toBase64();
201 auto* randomData = (uchar*)malloc(length);
203 RAND_bytes(randomData, length);
204 QByteArray data((
char*)randomData, length);
AesInterface(QObject *parent=nullptr)
static QByteArray createRandomData(int length)
QByteArray decrypt(const QByteArray &cipherData, const QByteArray &password)
QByteArray encrypt(const QByteArray &plainData, const QByteArray &password)
static QByteArray passwordToHash(const QString &masterPassword)