Secure settings rework
This commit is contained in:
parent
42398950e4
commit
b5890340e3
21 changed files with 1863 additions and 223 deletions
184
client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp
Normal file
184
client/3rd/QSimpleCrypto/sources/QBlockCipher.cpp
Normal file
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* Copyright 2021 BrutalWizard (https://github.com/bru74lw1z4rd). All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution
|
||||
**/
|
||||
|
||||
#include "include/QBlockCipher.h"
|
||||
|
||||
QSimpleCrypto::QBlockCipher::QBlockCipher()
|
||||
{
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QBlockCipher::generateRandomBytes - Function generates random bytes by size.
|
||||
/// \param size - Size of generated bytes.
|
||||
/// \return Returns random bytes.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QBlockCipher::generateRandomBytes(const int& size)
|
||||
{
|
||||
unsigned char arr[sizeof(size)];
|
||||
RAND_bytes(arr, sizeof(size));
|
||||
|
||||
QByteArray buffer = QByteArray(reinterpret_cast<char*>(arr), size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QBlockCipher::encryptAesBlockCipher - Function encrypts data with Aes Block Cipher algorithm.
|
||||
/// \param data - Data that will be encrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param password - Encryption password.
|
||||
/// \param salt - Random delta.
|
||||
/// \param rounds - Transformation rounds.
|
||||
/// \param chiper - Can be used with OpenSSL EVP_CIPHER (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc().
|
||||
/// \param md - Hash algroitm (OpenSSL EVP_MD). Example: EVP_sha512().
|
||||
/// \return Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QBlockCipher::encryptAesBlockCipher(QByteArray data, QByteArray key,
|
||||
QByteArray iv,
|
||||
const int& rounds, const EVP_CIPHER* cipher, const EVP_MD* md)
|
||||
{
|
||||
try {
|
||||
/* Initialize EVP_CIPHER_CTX */
|
||||
std::unique_ptr<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> encryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free };
|
||||
if (encryptionCipher == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize \'encryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Reinterpret values for multi use */
|
||||
unsigned char* m_key = reinterpret_cast<unsigned char*>(key.data());
|
||||
unsigned char* m_iv = reinterpret_cast<unsigned char*>(iv.data());
|
||||
|
||||
/* Set data length */
|
||||
int cipherTextLength(data.size() + AES_BLOCK_SIZE);
|
||||
int finalLength = 0;
|
||||
|
||||
/* Initialize cipcherText. Here encrypted data will be stored */
|
||||
std::unique_ptr<unsigned char[]> cipherText { new unsigned char[cipherTextLength]() };
|
||||
if (cipherText == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for 'cipherText'.");
|
||||
}
|
||||
|
||||
// Bug here
|
||||
// /* Start encryption with password based encryption routine */
|
||||
// if (!EVP_BytesToKey(cipher, md, reinterpret_cast<unsigned char*>(salt.data()), reinterpret_cast<unsigned char*>(password.data()), password.length(), rounds, m_key, m_iv)) {
|
||||
// throw std::runtime_error("Couldn't start encryption routine. EVP_BytesToKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
// }
|
||||
|
||||
/* Initialize encryption operation. */
|
||||
if (!EVP_EncryptInit_ex(encryptionCipher.get(), cipher, nullptr, m_key, m_iv)) {
|
||||
throw std::runtime_error("Couldn't initialize encryption operation. EVP_EncryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide the message to be encrypted, and obtain the encrypted output.
|
||||
* EVP_EncryptUpdate can be called multiple times if necessary
|
||||
*/
|
||||
if (!EVP_EncryptUpdate(encryptionCipher.get(), cipherText.get(), &cipherTextLength, reinterpret_cast<const unsigned char*>(data.data()), data.size())) {
|
||||
throw std::runtime_error("Couldn't provide message to be encrypted. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Finalize the encryption. Normally ciphertext bytes may be written at this stage */
|
||||
if (!EVP_EncryptFinal(encryptionCipher.get(), cipherText.get() + cipherTextLength, &finalLength)) {
|
||||
throw std::runtime_error("Couldn't finalize encryption. EVP_EncryptFinal(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Finilize data to be readable with qt */
|
||||
QByteArray encryptedData = QByteArray(reinterpret_cast<char*>(cipherText.get()), cipherTextLength + finalLength);
|
||||
|
||||
return encryptedData;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QBlockCipher::error.setError(1, exception.what());
|
||||
return QByteArray();
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QBlockCipher::error.setError(2, "Unknown error!");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QBlockCipher::encryptAesBlockCipher - Function decrypts data with Aes Block Cipher algorithm.
|
||||
/// \param data - Data that will be decrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param password - Decryption password.
|
||||
/// \param salt - Random delta.
|
||||
/// \param rounds - Transformation rounds.
|
||||
/// \param chiper - Can be used with OpenSSL EVP_CIPHER (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc().
|
||||
/// \param md - Hash algroitm (OpenSSL EVP_MD). Example: EVP_sha512().
|
||||
/// \return Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QBlockCipher::decryptAesBlockCipher(QByteArray data, QByteArray key,
|
||||
QByteArray iv,
|
||||
const int& rounds, const EVP_CIPHER* cipher, const EVP_MD* md)
|
||||
{
|
||||
try {
|
||||
/* Initialize EVP_CIPHER_CTX */
|
||||
std::unique_ptr<EVP_CIPHER_CTX, void (*)(EVP_CIPHER_CTX*)> decryptionCipher { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free };
|
||||
if (decryptionCipher == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize \'decryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Reinterpret values for multi use */
|
||||
unsigned char* m_key = reinterpret_cast<unsigned char*>(key.data());
|
||||
unsigned char* m_iv = reinterpret_cast<unsigned char*>(iv.data());
|
||||
|
||||
/* Set data length */
|
||||
int plainTextLength(data.size());
|
||||
int finalLength = 0;
|
||||
|
||||
/* Initialize plainText. Here decrypted data will be stored */
|
||||
std::unique_ptr<unsigned char[]> plainText { new unsigned char[plainTextLength + AES_BLOCK_SIZE]() };
|
||||
if (plainText == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for \'plainText\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
// Bug here
|
||||
// /* Start encryption with password based encryption routine */
|
||||
// if (!EVP_BytesToKey(cipher, md, reinterpret_cast<const unsigned char*>(salt.data()), reinterpret_cast<const unsigned char*>(password.data()), password.length(), rounds, m_key, m_iv)) {
|
||||
// throw std::runtime_error("Couldn't start decryption routine. EVP_BytesToKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
// }
|
||||
|
||||
/* Initialize decryption operation. */
|
||||
if (!EVP_DecryptInit_ex(decryptionCipher.get(), cipher, nullptr, m_key, m_iv)) {
|
||||
throw std::runtime_error("Couldn't initialize decryption operation. EVP_DecryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide the message to be decrypted, and obtain the plaintext output.
|
||||
* EVP_DecryptUpdate can be called multiple times if necessary
|
||||
*/
|
||||
if (!EVP_DecryptUpdate(decryptionCipher.get(), plainText.get(), &plainTextLength, reinterpret_cast<const unsigned char*>(data.data()), data.size())) {
|
||||
throw std::runtime_error("Couldn't provide message to be decrypted. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Finalize the decryption. A positive return value indicates success,
|
||||
* anything else is a failure - the plaintext is not trustworthy.
|
||||
*/
|
||||
if (!EVP_DecryptFinal(decryptionCipher.get(), plainText.get() + plainTextLength, &finalLength)) {
|
||||
throw std::runtime_error("Couldn't finalize decryption. EVP_DecryptFinal. Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Finilize data to be readable with qt */
|
||||
QByteArray decryptedData = QByteArray(reinterpret_cast<char*>(plainText.get()), plainTextLength + finalLength);
|
||||
|
||||
return decryptedData;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QBlockCipher::error.setError(1, exception.what());
|
||||
return QByteArray(exception.what());
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QBlockCipher::error.setError(2, "Unknown error!");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue