Secure settings rework
This commit is contained in:
parent
42398950e4
commit
b5890340e3
21 changed files with 1863 additions and 223 deletions
18
client/3rd/QSimpleCrypto/QSimpleCrypto.pri
Normal file
18
client/3rd/QSimpleCrypto/QSimpleCrypto.pri
Normal file
|
@ -0,0 +1,18 @@
|
|||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/include/QAead.h \
|
||||
$$PWD/include/QBlockCipher.h \
|
||||
$$PWD/include/QCryptoError.h \
|
||||
$$PWD/include/QRsa.h \
|
||||
$$PWD/include/QSimpleCrypto_global.h \
|
||||
$$PWD/include/QX509.h \
|
||||
$$PWD/include/QX509Store.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/sources/QAead.cpp \
|
||||
$$PWD/sources/QBlockCipher.cpp \
|
||||
$$PWD/sources/QCryptoError.cpp \
|
||||
$$PWD/sources/QRsa.cpp \
|
||||
$$PWD/sources/QX509.cpp \
|
||||
$$PWD/sources/QX509Store.cpp
|
87
client/3rd/QSimpleCrypto/include/QAead.h
Normal file
87
client/3rd/QSimpleCrypto/include/QAead.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* 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
|
||||
**/
|
||||
|
||||
#ifndef QAEAD_H
|
||||
#define QAEAD_H
|
||||
|
||||
#include "QSimpleCrypto_global.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "QCryptoError.h"
|
||||
|
||||
// clang-format off
|
||||
namespace QSimpleCrypto
|
||||
{
|
||||
class QSIMPLECRYPTO_EXPORT QAead {
|
||||
public:
|
||||
QAead();
|
||||
|
||||
///
|
||||
/// \brief encryptAesGcm - Function encrypts data with Gcm algorithm.
|
||||
/// \param data - Data that will be encrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param tag - Authorization tag.
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used.
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm().
|
||||
/// \return Returns encrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray encryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_gcm());
|
||||
|
||||
///
|
||||
/// \brief decryptAesGcm - Function decrypts data with Gcm algorithm.
|
||||
/// \param data - Data that will be decrypted
|
||||
/// \param key - AES key
|
||||
/// \param iv - Initialization vector
|
||||
/// \param tag - Authorization tag
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm()
|
||||
/// \return Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray decryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_gcm());
|
||||
|
||||
///
|
||||
/// \brief encryptAesCcm - Function encrypts data with Ccm algorithm.
|
||||
/// \param data - Data that will be encrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param tag - Authorization tag.
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used.
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm().
|
||||
/// \return Returns encrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray encryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_ccm());
|
||||
|
||||
///
|
||||
/// \brief decryptAesCcm - Function decrypts data with Ccm algorithm.
|
||||
/// \param data - Data that will be decrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param tag - Authorization tag.
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used.
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm().
|
||||
/// \return Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray decryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad = "", const EVP_CIPHER* cipher = EVP_aes_256_ccm());
|
||||
|
||||
///
|
||||
/// \brief error - Error handler class.
|
||||
///
|
||||
QCryptoError error;
|
||||
};
|
||||
} // namespace QSimpleCrypto
|
||||
|
||||
#endif // QAEAD_H
|
83
client/3rd/QSimpleCrypto/include/QBlockCipher.h
Normal file
83
client/3rd/QSimpleCrypto/include/QBlockCipher.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* 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
|
||||
**/
|
||||
|
||||
#ifndef QBLOCKCIPHER_H
|
||||
#define QBLOCKCIPHER_H
|
||||
|
||||
#include "QSimpleCrypto_global.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "QCryptoError.h"
|
||||
|
||||
// clang-format off
|
||||
namespace QSimpleCrypto
|
||||
{
|
||||
class QSIMPLECRYPTO_EXPORT QBlockCipher {
|
||||
|
||||
#define Aes128Rounds 10
|
||||
#define Aes192Rounds 12
|
||||
#define Aes256Rounds 14
|
||||
|
||||
public:
|
||||
QBlockCipher();
|
||||
|
||||
///
|
||||
/// \brief generateRandomBytes - Function generates random bytes by size.
|
||||
/// \param size - Size of generated bytes.
|
||||
/// \return Returns random bytes.
|
||||
///
|
||||
QByteArray generateRandomBytes(const int& size);
|
||||
|
||||
///
|
||||
/// \brief 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 encryptAesBlockCipher(QByteArray data, QByteArray key,
|
||||
QByteArray iv = "", const int& rounds = Aes256Rounds,
|
||||
const EVP_CIPHER* cipher = EVP_aes_256_cbc(), const EVP_MD* md = EVP_sha512());
|
||||
|
||||
///
|
||||
/// \brief decryptAesBlockCipher - 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 decryptAesBlockCipher(QByteArray data, QByteArray key,
|
||||
QByteArray iv = "", const int& rounds = Aes256Rounds,
|
||||
const EVP_CIPHER* cipher = EVP_aes_256_cbc(), const EVP_MD* md = EVP_sha512());
|
||||
|
||||
///
|
||||
/// \brief error - Error handler class.
|
||||
///
|
||||
QCryptoError error;
|
||||
};
|
||||
} // namespace QSimpleCrypto
|
||||
|
||||
#endif // QBLOCKCIPHER_H
|
45
client/3rd/QSimpleCrypto/include/QCryptoError.h
Normal file
45
client/3rd/QSimpleCrypto/include/QCryptoError.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef QCRYPTOERROR_H
|
||||
#define QCRYPTOERROR_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "QSimpleCrypto_global.h"
|
||||
|
||||
/// TODO: Add Special error code for each error.
|
||||
|
||||
// clang-format off
|
||||
namespace QSimpleCrypto
|
||||
{
|
||||
class QSIMPLECRYPTO_EXPORT QCryptoError : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QCryptoError(QObject* parent = nullptr);
|
||||
|
||||
///
|
||||
/// \brief setError - Sets error information
|
||||
/// \param errorCode - Error code.
|
||||
/// \param errorSummary - Error summary.
|
||||
///
|
||||
inline void setError(const quint8 errorCode, const QString& errorSummary)
|
||||
{
|
||||
m_currentErrorCode = errorCode;
|
||||
m_errorSummary = errorSummary;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief lastError - Returns last error.
|
||||
/// \return Returns eror ID and error Text.
|
||||
///
|
||||
inline QPair<quint8, QString> lastError() const
|
||||
{
|
||||
return QPair<quint8, QString>(m_currentErrorCode, m_errorSummary);
|
||||
}
|
||||
|
||||
private:
|
||||
quint8 m_currentErrorCode;
|
||||
QString m_errorSummary;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // QCRYPTOERROR_H
|
104
client/3rd/QSimpleCrypto/include/QRsa.h
Normal file
104
client/3rd/QSimpleCrypto/include/QRsa.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* 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
|
||||
**/
|
||||
|
||||
#ifndef QRSA_H
|
||||
#define QRSA_H
|
||||
|
||||
#include "QSimpleCrypto_global.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "QCryptoError.h"
|
||||
|
||||
// clang-format off
|
||||
namespace QSimpleCrypto
|
||||
{
|
||||
class QSIMPLECRYPTO_EXPORT QRsa {
|
||||
|
||||
#define PublicEncrypt 0
|
||||
#define PrivateEncrypt 1
|
||||
#define PublicDecrypt 2
|
||||
#define PrivateDecrypt 3
|
||||
|
||||
public:
|
||||
QRsa();
|
||||
|
||||
///
|
||||
/// \brief generateRsaKeys - Function generate Rsa Keys and returns them in OpenSSL structure.
|
||||
/// \param bits - RSA key size.
|
||||
/// \param rsaBigNumber - The exponent is an odd number, typically 3, 17 or 65537.
|
||||
/// \return Returns 'OpenSSL RSA structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'RSA_free()' to avoid memory leak.
|
||||
///
|
||||
RSA* generateRsaKeys(const int& bits, const int& rsaBigNumber);
|
||||
|
||||
///
|
||||
/// \brief savePublicKey - Saves to file RSA public key.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param publicKeyFileName - Public key file name.
|
||||
///
|
||||
void savePublicKey(RSA *rsa, const QByteArray& publicKeyFileName);
|
||||
|
||||
///
|
||||
/// \brief savePrivateKey - Saves to file RSA private key.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param privateKeyFileName - Private key file name.
|
||||
/// \param password - Private key password.
|
||||
/// \param cipher - Can be used with 'OpenSSL EVP_CIPHER' (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc().
|
||||
///
|
||||
void savePrivateKey(RSA* rsa, const QByteArray& privateKeyFileName, QByteArray password = "", const EVP_CIPHER* cipher = nullptr);
|
||||
|
||||
///
|
||||
/// \brief getPublicKeyFromFile - Gets RSA public key from a file.
|
||||
/// \param filePath - File path to public key file.
|
||||
/// \return Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak.
|
||||
///
|
||||
EVP_PKEY* getPublicKeyFromFile(const QByteArray& filePath);
|
||||
|
||||
///
|
||||
/// \brief getPrivateKeyFromFile - Gets RSA private key from a file.
|
||||
/// \param filePath - File path to private key file.
|
||||
/// \param password - Private key password.
|
||||
/// \return - Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak.
|
||||
///
|
||||
EVP_PKEY* getPrivateKeyFromFile(const QByteArray& filePath, const QByteArray& password = "");
|
||||
|
||||
///
|
||||
/// \brief encrypt - Encrypt data with RSA algorithm.
|
||||
/// \param plaintext - Text that must be encrypted.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param encryptType - Public or private encrypt type. (PUBLIC_ENCRYPT, PRIVATE_ENCRYPT).
|
||||
/// \param padding - OpenSSL RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc.
|
||||
/// \return Returns encrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray encrypt(QByteArray plainText, RSA* rsa, const int& encryptType = PublicEncrypt, const int& padding = RSA_PKCS1_PADDING);
|
||||
|
||||
///
|
||||
/// \brief decrypt - Decrypt data with RSA algorithm.
|
||||
/// \param cipherText - Text that must be decrypted.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param decryptType - Public or private type. (PUBLIC_DECRYPT, PRIVATE_DECRYPT).
|
||||
/// \param padding - RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc.
|
||||
/// \return - Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray decrypt(QByteArray cipherText, RSA* rsa, const int& decryptType = PrivateDecrypt, const int& padding = RSA_PKCS1_PADDING);
|
||||
|
||||
///
|
||||
/// \brief error - Error handler class.
|
||||
///
|
||||
QCryptoError error;
|
||||
};
|
||||
} // namespace QSimpleCrypto
|
||||
|
||||
#endif // QRSA_H
|
9
client/3rd/QSimpleCrypto/include/QSimpleCrypto_global.h
Normal file
9
client/3rd/QSimpleCrypto/include/QSimpleCrypto_global.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef QSIMPLECRYPTO_GLOBAL_H
|
||||
#define QSIMPLECRYPTO_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#define QSIMPLECRYPTO_EXPORT
|
||||
|
||||
#endif // QSIMPLECRYPTO_GLOBAL_H
|
87
client/3rd/QSimpleCrypto/include/QX509.h
Normal file
87
client/3rd/QSimpleCrypto/include/QX509.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* 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
|
||||
**/
|
||||
|
||||
#ifndef QX509_H
|
||||
#define QX509_H
|
||||
|
||||
#include "QSimpleCrypto_global.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
|
||||
#include "QCryptoError.h"
|
||||
|
||||
// clang-format off
|
||||
namespace QSimpleCrypto
|
||||
{
|
||||
class QSIMPLECRYPTO_EXPORT QX509 {
|
||||
|
||||
#define oneYear 31536000L
|
||||
#define x509LastVersion 2
|
||||
|
||||
public:
|
||||
QX509();
|
||||
|
||||
///
|
||||
/// \brief loadCertificateFromFile - Function load X509 from file and returns OpenSSL structure.
|
||||
/// \param fileName - File path to certificate.
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak.
|
||||
///
|
||||
X509* loadCertificateFromFile(const QByteArray& fileName);
|
||||
|
||||
///
|
||||
/// \brief signCertificate - Function signs X509 certificate and returns signed X509 OpenSSL structure.
|
||||
/// \param endCertificate - Certificate that will be signed
|
||||
/// \param caCertificate - CA certificate that will sign end certificate
|
||||
/// \param caPrivateKey - CA certificate private key
|
||||
/// \param fileName - With that name certificate will be saved. Leave "", if don't need to save it
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened.
|
||||
///
|
||||
X509* signCertificate(X509* endCertificate, X509* caCertificate, EVP_PKEY* caPrivateKey, const QByteArray& fileName = "");
|
||||
|
||||
///
|
||||
/// \brief verifyCertificate - Function verifies X509 certificate and returns verified X509 OpenSSL structure.
|
||||
/// \param x509 - OpenSSL X509. That certificate will be verified.
|
||||
/// \param store - Trusted certificate must be added to X509_Store with 'addCertificateToStore(X509_STORE* ctx, X509* x509)'.
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened
|
||||
///
|
||||
X509* verifyCertificate(X509* x509, X509_STORE* store);
|
||||
|
||||
///
|
||||
/// \brief generateSelfSignedCertificate - Function generatesand returns self signed X509.
|
||||
/// \param rsa - OpenSSL RSA.
|
||||
/// \param additionalData - Certificate information.
|
||||
/// \param certificateFileName - With that name certificate will be saved. Leave "", if don't need to save it.
|
||||
/// \param md - OpenSSL EVP_MD structure. Example: EVP_sha512().
|
||||
/// \param serialNumber - X509 certificate serial number.
|
||||
/// \param version - X509 certificate version.
|
||||
/// \param notBefore - X509 start date.
|
||||
/// \param notAfter - X509 end date.
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak.
|
||||
///
|
||||
X509* generateSelfSignedCertificate(const RSA* rsa, const QMap<QByteArray, QByteArray>& additionalData,
|
||||
const QByteArray& certificateFileName = "", const EVP_MD* md = EVP_sha512(),
|
||||
const long& serialNumber = 1, const long& version = x509LastVersion,
|
||||
const long& notBefore = 0, const long& notAfter = oneYear);
|
||||
|
||||
///
|
||||
/// \brief error - Error handler class.
|
||||
///
|
||||
QCryptoError error;
|
||||
};
|
||||
} // namespace QSimpleCrypto
|
||||
|
||||
#endif // QX509_H
|
120
client/3rd/QSimpleCrypto/include/QX509Store.h
Normal file
120
client/3rd/QSimpleCrypto/include/QX509Store.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* 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
|
||||
**/
|
||||
|
||||
#ifndef QX509STORE_H
|
||||
#define QX509STORE_H
|
||||
|
||||
#include "QSimpleCrypto_global.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <openssl/x509v3.h>
|
||||
|
||||
#include "QCryptoError.h"
|
||||
|
||||
// clang-format off
|
||||
namespace QSimpleCrypto
|
||||
{
|
||||
class QSIMPLECRYPTO_EXPORT QX509Store {
|
||||
public:
|
||||
QX509Store();
|
||||
|
||||
///
|
||||
/// \brief addCertificateToStore
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param x509 - OpenSSL X509.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool addCertificateToStore(X509_STORE* store, X509* x509);
|
||||
|
||||
///
|
||||
/// \brief addLookup
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param method - OpenSSL X509_LOOKUP_METHOD. Example: X509_LOOKUP_file.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool addLookup(X509_STORE* store, X509_LOOKUP_METHOD* method);
|
||||
|
||||
///
|
||||
/// \brief setCertificateDepth
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param depth - That is the maximum number of untrusted CA certificates that can appear in a chain. Example: 0.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool setDepth(X509_STORE* store, const int& depth);
|
||||
|
||||
///
|
||||
/// \brief setFlag
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param flag - The verification flags consists of zero or more of the following flags ored together. Example: X509_V_FLAG_CRL_CHECK.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool setFlag(X509_STORE* store, const unsigned long& flag);
|
||||
|
||||
///
|
||||
/// \brief setFlag
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param purpose - Verification purpose in param to purpose. Example: X509_PURPOSE_ANY.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool setPurpose(X509_STORE* store, const int& purpose);
|
||||
|
||||
///
|
||||
/// \brief setTrust
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param trust - Trust Level. Example: X509_TRUST_SSL_SERVER.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool setTrust(X509_STORE* store, const int& trust);
|
||||
|
||||
///
|
||||
/// \brief setDefaultPaths
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool setDefaultPaths(X509_STORE* store);
|
||||
|
||||
///
|
||||
/// \brief loadLocations
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param fileName - File name. Example: "caCertificate.pem".
|
||||
/// \param dirPath - Path to file. Example: "path/To/File".
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool loadLocations(X509_STORE* store, const QByteArray& fileName, const QByteArray& dirPath);
|
||||
|
||||
///
|
||||
/// \brief loadLocations
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param file - Qt QFile that will be loaded.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool loadLocations(X509_STORE* store, const QFile& file);
|
||||
|
||||
///
|
||||
/// \brief loadLocations
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param fileInfo - Qt QFileInfo.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool loadLocations(X509_STORE* store, const QFileInfo& fileInfo);
|
||||
|
||||
///
|
||||
/// \brief error - Error handler class.
|
||||
///
|
||||
QCryptoError error;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // QX509STORE_H
|
364
client/3rd/QSimpleCrypto/sources/QAead.cpp
Normal file
364
client/3rd/QSimpleCrypto/sources/QAead.cpp
Normal file
|
@ -0,0 +1,364 @@
|
|||
/**
|
||||
* 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/QAead.h"
|
||||
|
||||
QSimpleCrypto::QAead::QAead()
|
||||
{
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QAEAD::encryptAesGcm - Function encrypts data with Gcm algorithm.
|
||||
/// \param data - Data that will be encrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param tag - Authorization tag.
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used.
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm().
|
||||
/// \return Returns encrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QAead::encryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
|
||||
/* Set data length */
|
||||
int plainTextLength = data.size();
|
||||
int cipherTextLength = 0;
|
||||
|
||||
/* Initialize cipherText. Here encrypted data will be stored */
|
||||
std::unique_ptr<unsigned char[]> cipherText { new unsigned char[plainTextLength]() };
|
||||
if (cipherText == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for 'ciphertext'.");
|
||||
}
|
||||
|
||||
/* Initialize encryption operation. */
|
||||
if (!EVP_EncryptInit_ex(encryptionCipher.get(), cipher, nullptr, reinterpret_cast<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(iv.data()))) {
|
||||
throw std::runtime_error("Couldn't initialize encryption operation. EVP_EncryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set IV length if default 12 bytes (96 bits) is not appropriate */
|
||||
if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_GCM_SET_IVLEN, iv.length(), nullptr)) {
|
||||
throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
// /* Check if aad need to be used */
|
||||
// if (aad.length() > 0) {
|
||||
// /* Provide any AAD data. This can be called zero or more times as required */
|
||||
// if (!EVP_EncryptUpdate(encryptionCipher.get(), nullptr, &cipherTextLength, reinterpret_cast<unsigned char*>(aad.data()), aad.length())) {
|
||||
// throw std::runtime_error("Couldn't provide aad data. EVP_EncryptUpdate(). 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()), plainTextLength)) {
|
||||
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 cipher text bytes may be written at
|
||||
* this stage, but this does not occur in GCM mode
|
||||
*/
|
||||
if (!EVP_EncryptFinal_ex(encryptionCipher.get(), cipherText.get(), &plainTextLength)) {
|
||||
throw std::runtime_error("Couldn't finalize encryption. EVP_EncryptFinal_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
// /* Get tag */
|
||||
// if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_GCM_GET_TAG, tag->length(), reinterpret_cast<unsigned char*>(tag->data()))) {
|
||||
// throw std::runtime_error("Couldn't get tag. EVP_CIPHER_CTX_ctrl(. 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);
|
||||
|
||||
return encryptedData;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QAead::error.setError(1, exception.what());
|
||||
return QByteArray();
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QAead::error.setError(2, "Unknown error!");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QAEAD::decryptAesGcm - Function decrypts data with Gcm algorithm.
|
||||
/// \param data - Data that will be decrypted
|
||||
/// \param key - AES key
|
||||
/// \param iv - Initialization vector
|
||||
/// \param tag - Authorization tag
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (gcm) - 128, 192, 256. Example: EVP_aes_256_gcm()
|
||||
/// \return Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QAead::decryptAesGcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher)
|
||||
{
|
||||
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.get() == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize \'decryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set data length */
|
||||
int cipherTextLength = data.size();
|
||||
int plainTextLength = 0;
|
||||
|
||||
/* Initialize plainText. Here decrypted data will be stored */
|
||||
std::unique_ptr<unsigned char[]> plainText { new unsigned char[cipherTextLength]() };
|
||||
if (plainText == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for 'plaintext'.");
|
||||
}
|
||||
|
||||
/* Initialize decryption operation. */
|
||||
if (!EVP_DecryptInit_ex(decryptionCipher.get(), cipher, nullptr, reinterpret_cast<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(iv.data()))) {
|
||||
throw std::runtime_error("Couldn't initialize decryption operation. EVP_DecryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set IV length. Not necessary if this is 12 bytes (96 bits) */
|
||||
if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_GCM_SET_IVLEN, iv.length(), nullptr)) {
|
||||
throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
// /* Check if aad need to be used */
|
||||
// if (aad.length() > 0) {
|
||||
// /* Provide any AAD data. This can be called zero or more times as required */
|
||||
// if (!EVP_DecryptUpdate(decryptionCipher.get(), nullptr, &plainTextLength, reinterpret_cast<unsigned char*>(aad.data()), aad.length())) {
|
||||
// throw std::runtime_error("Couldn't provide aad data. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
// }
|
||||
// }
|
||||
|
||||
/*
|
||||
* Provide the message to be decrypted, and obtain the plain text 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()), cipherTextLength)) {
|
||||
throw std::runtime_error("Couldn't provide message to be decrypted. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
// /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
|
||||
// if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_GCM_SET_TAG, tag->length(), reinterpret_cast<unsigned char*>(tag->data()))) {
|
||||
// throw std::runtime_error("Coldn't set tag. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
// }
|
||||
|
||||
/*
|
||||
* Finalize the decryption. A positive return value indicates success,
|
||||
* anything else is a failure - the plain text is not trustworthy.
|
||||
*/
|
||||
if (!EVP_DecryptFinal_ex(decryptionCipher.get(), plainText.get(), &cipherTextLength)) {
|
||||
throw std::runtime_error("Couldn't finalize decryption. EVP_DecryptFinal_ex(). 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);
|
||||
|
||||
return decryptedData;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QAead::error.setError(1, exception.what());
|
||||
return QByteArray();
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QAead::error.setError(2, "Unknown error!");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QAEAD::encryptAesCcm - Function encrypts data with Ccm algorithm.
|
||||
/// \param data - Data that will be encrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param tag - Authorization tag.
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used.
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm().
|
||||
/// \return Returns encrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QAead::encryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher)
|
||||
{
|
||||
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)));
|
||||
}
|
||||
|
||||
/* Set data length */
|
||||
int plainTextLength = data.size();
|
||||
int cipherTextLength = 0;
|
||||
|
||||
/* Initialize cipherText. Here encrypted data will be stored */
|
||||
std::unique_ptr<unsigned char[]> cipherText { new unsigned char[plainTextLength]() };
|
||||
if (cipherText.get() == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for 'ciphertext'.");
|
||||
}
|
||||
|
||||
/* Initialize encryption operation. */
|
||||
if (!EVP_EncryptInit_ex(encryptionCipher.get(), cipher, nullptr, reinterpret_cast<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(iv.data()))) {
|
||||
throw std::runtime_error("Couldn't initialize encryption operation. EVP_EncryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set IV length if default 12 bytes (96 bits) is not appropriate */
|
||||
if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_CCM_SET_IVLEN, iv.length(), nullptr)) {
|
||||
throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set tag length */
|
||||
if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_CCM_SET_TAG, tag->length(), nullptr)) {
|
||||
throw std::runtime_error("Coldn't set tag. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Check if aad need to be used */
|
||||
if (aad.length() > 0) {
|
||||
/* Provide the total plain text length */
|
||||
if (!EVP_EncryptUpdate(encryptionCipher.get(), nullptr, &cipherTextLength, nullptr, plainTextLength)) {
|
||||
throw std::runtime_error("Couldn't provide total plaintext length. EVP_EncryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Provide any AAD data. This can be called zero or more times as required */
|
||||
if (!EVP_EncryptUpdate(encryptionCipher.get(), nullptr, &cipherTextLength, reinterpret_cast<unsigned char*>(aad.data()), aad.length())) {
|
||||
throw std::runtime_error("Couldn't provide aad data. EVP_EncryptUpdate(). 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()), plainTextLength)) {
|
||||
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, but this does not occur in GCM mode
|
||||
*/
|
||||
if (!EVP_EncryptFinal_ex(encryptionCipher.get(), cipherText.get(), &plainTextLength)) {
|
||||
throw std::runtime_error("Couldn't finalize encryption. EVP_EncryptFinal_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Get tag */
|
||||
if (!EVP_CIPHER_CTX_ctrl(encryptionCipher.get(), EVP_CTRL_CCM_GET_TAG, tag->length(), reinterpret_cast<unsigned char*>(tag->data()))) {
|
||||
throw std::runtime_error("Couldn't get tag. EVP_CIPHER_CTX_ctrl(). 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);
|
||||
|
||||
return encryptedData;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QAead::error.setError(1, exception.what());
|
||||
return QByteArray();
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QAead::error.setError(2, "Unknown error!");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QAEAD::decryptAesCcm - Function decrypts data with Ccm algorithm.
|
||||
/// \param data - Data that will be decrypted.
|
||||
/// \param key - AES key.
|
||||
/// \param iv - Initialization vector.
|
||||
/// \param tag - Authorization tag.
|
||||
/// \param aad - Additional authenticated data. Must be nullptr, if not used.
|
||||
/// \param cipher - Can be used with OpenSSL EVP_CIPHER (ccm) - 128, 192, 256. Example: EVP_aes_256_ccm().
|
||||
/// \return Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QAead::decryptAesCcm(QByteArray data, QByteArray key, QByteArray iv, QByteArray* tag, QByteArray aad, const EVP_CIPHER* cipher)
|
||||
{
|
||||
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.get() == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize \'decryptionCipher\'. EVP_CIPHER_CTX_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set data length */
|
||||
int cipherTextLength = data.size();
|
||||
int plainTextLength = 0;
|
||||
|
||||
/* Initialize plainText. Here decrypted data will be stored */
|
||||
std::unique_ptr<unsigned char[]> plainText { new unsigned char[cipherTextLength]() };
|
||||
if (plainText == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for 'plaintext'.");
|
||||
}
|
||||
|
||||
/* Initialize decryption operation. */
|
||||
if (!EVP_DecryptInit_ex(decryptionCipher.get(), cipher, nullptr, reinterpret_cast<unsigned char*>(key.data()), reinterpret_cast<unsigned char*>(iv.data()))) {
|
||||
throw std::runtime_error("Couldn't initialize decryption operation. EVP_DecryptInit_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set IV length. Not necessary if this is 12 bytes (96 bits) */
|
||||
if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_CCM_SET_IVLEN, iv.length(), nullptr)) {
|
||||
throw std::runtime_error("Couldn't set IV length. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set expected tag value. Works in OpenSSL 1.0.1d and later */
|
||||
if (!EVP_CIPHER_CTX_ctrl(decryptionCipher.get(), EVP_CTRL_CCM_SET_TAG, tag->length(), reinterpret_cast<unsigned char*>(tag->data()))) {
|
||||
throw std::runtime_error("Coldn't set tag. EVP_CIPHER_CTX_ctrl(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Check if aad need to be used */
|
||||
if (aad.length() > 0) {
|
||||
/* Provide the total ciphertext length */
|
||||
if (!EVP_DecryptUpdate(decryptionCipher.get(), nullptr, &plainTextLength, nullptr, cipherTextLength)) {
|
||||
throw std::runtime_error("Couldn't provide total plaintext length. EVP_DecryptUpdate(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Provide any AAD data. This can be called zero or more times as required */
|
||||
if (!EVP_DecryptUpdate(decryptionCipher.get(), nullptr, &plainTextLength, reinterpret_cast<unsigned char*>(aad.data()), aad.length())) {
|
||||
throw std::runtime_error("Couldn't provide aad data. EVP_DecryptUpdate(). 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()), cipherTextLength)) {
|
||||
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_ex(decryptionCipher.get(), plainText.get(), &cipherTextLength)) {
|
||||
throw std::runtime_error("Couldn't finalize decryption. EVP_DecryptFinal_ex(). 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);
|
||||
|
||||
return decryptedData;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QAead::error.setError(1, exception.what());
|
||||
return QByteArray();
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QAead::error.setError(2, "Unknown error!");
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
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();
|
||||
}
|
6
client/3rd/QSimpleCrypto/sources/QCryptoError.cpp
Normal file
6
client/3rd/QSimpleCrypto/sources/QCryptoError.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "include/QCryptoError.h"
|
||||
|
||||
QSimpleCrypto::QCryptoError::QCryptoError(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
274
client/3rd/QSimpleCrypto/sources/QRsa.cpp
Normal file
274
client/3rd/QSimpleCrypto/sources/QRsa.cpp
Normal file
|
@ -0,0 +1,274 @@
|
|||
/**
|
||||
* 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/QRsa.h"
|
||||
|
||||
QSimpleCrypto::QRsa::QRsa()
|
||||
{
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QRSA::generateRsaKeys - Function generate Rsa Keys and returns them in OpenSSL structure.
|
||||
/// \param bits - RSA key size.
|
||||
/// \param rsaBigNumber - The exponent is an odd number, typically 3, 17 or 65537.
|
||||
/// \return Returns 'OpenSSL RSA structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'RSA_free()' to avoid memory leak.
|
||||
///
|
||||
RSA* QSimpleCrypto::QRsa::generateRsaKeys(const int& bits, const int& rsaBigNumber)
|
||||
{
|
||||
try {
|
||||
/* Initialize big number */
|
||||
std::unique_ptr<BIGNUM, void (*)(BIGNUM*)> bigNumber { BN_new(), BN_free };
|
||||
if (bigNumber == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize \'bigNumber\'. BN_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Set big number */
|
||||
if (!BN_set_word(bigNumber.get(), rsaBigNumber)) {
|
||||
throw std::runtime_error("Couldn't set bigNumber. BN_set_word(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Initialize RSA */
|
||||
RSA* rsa = nullptr;
|
||||
if (!(rsa = RSA_new())) {
|
||||
throw std::runtime_error("Couldn't initialize x509. X509_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Generate key pair and store it in RSA */
|
||||
if (!RSA_generate_key_ex(rsa, bits, bigNumber.get(), nullptr)) {
|
||||
throw std::runtime_error("Couldn't generate RSA. RSA_generate_key_ex(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
return rsa;
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QRsa::error.setError(1, exception.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QRsa::error.setError(2, "Unknown error!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QRSA::savePublicKey - Saves to file RSA public key.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param publicKeyFileName - Public key file name.
|
||||
///
|
||||
void QSimpleCrypto::QRsa::savePublicKey(RSA* rsa, const QByteArray& publicKeyFileName)
|
||||
{
|
||||
try {
|
||||
/* Initialize BIO */
|
||||
std::unique_ptr<BIO, void (*)(BIO*)> bioPublicKey { BIO_new_file(publicKeyFileName.data(), "w+"), BIO_free_all };
|
||||
if (bioPublicKey == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize \'bioPublicKey\'. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write public key on file */
|
||||
if (!PEM_write_bio_RSA_PUBKEY(bioPublicKey.get(), rsa)) {
|
||||
throw std::runtime_error("Couldn't save public key. PEM_write_bio_RSAPublicKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QRsa::error.setError(1, exception.what());
|
||||
return;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QRsa::error.setError(2, "Unknown error!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QRSA::savePrivateKey - Saves to file RSA private key.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param privateKeyFileName - Private key file name.
|
||||
/// \param password - Private key password.
|
||||
/// \param cipher - Can be used with 'OpenSSL EVP_CIPHER' (ecb, cbc, cfb, ofb, ctr) - 128, 192, 256. Example: EVP_aes_256_cbc().
|
||||
///
|
||||
void QSimpleCrypto::QRsa::savePrivateKey(RSA* rsa, const QByteArray& privateKeyFileName, QByteArray password, const EVP_CIPHER* cipher)
|
||||
{
|
||||
try {
|
||||
/* Initialize BIO */
|
||||
std::unique_ptr<BIO, void (*)(BIO*)> bioPrivateKey { BIO_new_file(privateKeyFileName.data(), "w+"), BIO_free_all };
|
||||
if (bioPrivateKey == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize bioPrivateKey. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write private key to file */
|
||||
if (!PEM_write_bio_RSAPrivateKey(bioPrivateKey.get(), rsa, cipher, reinterpret_cast<unsigned char*>(password.data()), password.size(), nullptr, nullptr)) {
|
||||
throw std::runtime_error("Couldn't save private key. PEM_write_bio_RSAPrivateKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QRsa::error.setError(1, exception.what());
|
||||
return;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QRsa::error.setError(2, "Unknown error!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QRSA::getPublicKeyFromFile - Gets RSA public key from a file.
|
||||
/// \param filePath - File path to public key file.
|
||||
/// \return Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak.
|
||||
///
|
||||
EVP_PKEY* QSimpleCrypto::QRsa::getPublicKeyFromFile(const QByteArray& filePath)
|
||||
{
|
||||
try {
|
||||
/* Initialize BIO */
|
||||
std::unique_ptr<BIO, void (*)(BIO*)> bioPublicKey { BIO_new_file(filePath.data(), "r"), BIO_free_all };
|
||||
if (bioPublicKey == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize bioPublicKey. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Initialize EVP_PKEY */
|
||||
EVP_PKEY* keyStore = nullptr;
|
||||
if (!(keyStore = EVP_PKEY_new())) {
|
||||
throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write private key to file */
|
||||
if (!PEM_read_bio_PUBKEY(bioPublicKey.get(), &keyStore, nullptr, nullptr)) {
|
||||
throw std::runtime_error("Couldn't read private key. PEM_read_bio_PrivateKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
return keyStore;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QRsa::error.setError(1, exception.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QRsa::error.setError(2, "Unknown error!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QRSA::getPrivateKeyFromFile - Gets RSA private key from a file.
|
||||
/// \param filePath - File path to private key file.
|
||||
/// \param password - Private key password.
|
||||
/// \return - Returns 'OpenSSL EVP_PKEY structure' or 'nullptr', if error happened. Returned value must be cleaned up with 'EVP_PKEY_free()' to avoid memory leak.
|
||||
///
|
||||
EVP_PKEY* QSimpleCrypto::QRsa::getPrivateKeyFromFile(const QByteArray& filePath, const QByteArray& password)
|
||||
{
|
||||
try {
|
||||
/* Initialize BIO */
|
||||
std::unique_ptr<BIO, void (*)(BIO*)> bioPrivateKey { BIO_new_file(filePath.data(), "r"), BIO_free_all };
|
||||
if (bioPrivateKey == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize bioPrivateKey. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Initialize EVP_PKEY */
|
||||
EVP_PKEY* keyStore = nullptr;
|
||||
if (!(keyStore = EVP_PKEY_new())) {
|
||||
throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write private key to file */
|
||||
if (!PEM_read_bio_PrivateKey(bioPrivateKey.get(), &keyStore, nullptr, (void*)password.data())) {
|
||||
throw std::runtime_error("Couldn't read private key. PEM_read_bio_PrivateKey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
return keyStore;
|
||||
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QRsa::error.setError(1, exception.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QRsa::error.setError(2, "Unknown error!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QRSA::encrypt - Encrypt data with RSA algorithm.
|
||||
/// \param plaintext - Text that must be encrypted.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param encryptType - Public or private encrypt type. (PUBLIC_ENCRYPT, PRIVATE_ENCRYPT).
|
||||
/// \param padding - OpenSSL RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc.
|
||||
/// \return Returns encrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QRsa::encrypt(QByteArray plainText, RSA* rsa, const int& encryptType, const int& padding)
|
||||
{
|
||||
try {
|
||||
/* Initialize array. Here encrypted data will be saved */
|
||||
std::unique_ptr<unsigned char[]> cipherText { new unsigned char[RSA_size(rsa)]() };
|
||||
if (cipherText == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for 'cipherText'.");
|
||||
}
|
||||
|
||||
/* Result of encryption operation */
|
||||
short int result = 0;
|
||||
|
||||
/* Execute encryption operation */
|
||||
if (encryptType == PublicDecrypt) {
|
||||
result = RSA_public_encrypt(plainText.size(), reinterpret_cast<unsigned char*>(plainText.data()), cipherText.get(), rsa, padding);
|
||||
} else if (encryptType == PrivateDecrypt) {
|
||||
result = RSA_private_encrypt(plainText.size(), reinterpret_cast<unsigned char*>(plainText.data()), cipherText.get(), rsa, padding);
|
||||
}
|
||||
|
||||
/* Check for result */
|
||||
if (result <= -1) {
|
||||
throw std::runtime_error("Couldn't encrypt data. Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Get encrypted data */
|
||||
const QByteArray& encryptedData = QByteArray(reinterpret_cast<char*>(cipherText.get()), RSA_size(rsa));
|
||||
|
||||
return encryptedData;
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QRsa::error.setError(1, exception.what());
|
||||
return "";
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QRsa::error.setError(2, "Unknown error!");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QRSA::decrypt - Decrypt data with RSA algorithm.
|
||||
/// \param cipherText - Text that must be decrypted.
|
||||
/// \param rsa - OpenSSL RSA structure.
|
||||
/// \param decryptType - Public or private type. (PUBLIC_DECRYPT, PRIVATE_DECRYPT).
|
||||
/// \param padding - RSA padding can be used with: 'RSA_PKCS1_PADDING', 'RSA_NO_PADDING' and etc.
|
||||
/// \return - Returns decrypted data or "", if error happened.
|
||||
///
|
||||
QByteArray QSimpleCrypto::QRsa::decrypt(QByteArray cipherText, RSA* rsa, const int& decryptType, const int& padding)
|
||||
{
|
||||
try {
|
||||
/* Initialize array. Here decrypted data will be saved */
|
||||
std::unique_ptr<unsigned char[]> plainText { new unsigned char[cipherText.size()]() };
|
||||
if (plainText == nullptr) {
|
||||
throw std::runtime_error("Couldn't allocate memory for 'plainText'.");
|
||||
}
|
||||
|
||||
/* Result of decryption operation */
|
||||
short int result = 0;
|
||||
|
||||
/* Execute decryption operation */
|
||||
if (decryptType == PublicDecrypt) {
|
||||
result = RSA_public_decrypt(RSA_size(rsa), reinterpret_cast<unsigned char*>(cipherText.data()), plainText.get(), rsa, padding);
|
||||
} else if (decryptType == PrivateDecrypt) {
|
||||
result = RSA_private_decrypt(RSA_size(rsa), reinterpret_cast<unsigned char*>(cipherText.data()), plainText.get(), rsa, padding);
|
||||
}
|
||||
|
||||
/* Check for result */
|
||||
if (result <= -1) {
|
||||
throw std::runtime_error("Couldn't decrypt data. Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Get decrypted data */
|
||||
const QByteArray& decryptedData = QByteArray(reinterpret_cast<char*>(plainText.get()));
|
||||
|
||||
return decryptedData;
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QRsa::error.setError(1, exception.what());
|
||||
return "";
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QRsa::error.setError(2, "Unknown error!");
|
||||
return "";
|
||||
}
|
||||
}
|
234
client/3rd/QSimpleCrypto/sources/QX509.cpp
Normal file
234
client/3rd/QSimpleCrypto/sources/QX509.cpp
Normal file
|
@ -0,0 +1,234 @@
|
|||
/**
|
||||
* 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/QX509.h"
|
||||
|
||||
QSimpleCrypto::QX509::QX509()
|
||||
{
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509::loadCertificateFromFile - Function load X509 from file and returns OpenSSL structure.
|
||||
/// \param fileName - File path to certificate.
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak.
|
||||
///
|
||||
X509* QSimpleCrypto::QX509::loadCertificateFromFile(const QByteArray& fileName)
|
||||
{
|
||||
try {
|
||||
/* Initialize X509 */
|
||||
X509* x509 = nullptr;
|
||||
if (!(x509 = X509_new())) {
|
||||
throw std::runtime_error("Couldn't initialize X509. X509_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Initialize BIO */
|
||||
std::unique_ptr<BIO, void (*)(BIO*)> certFile { BIO_new_file(fileName.data(), "r+"), BIO_free_all };
|
||||
if (certFile == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize certFile. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Read file */
|
||||
if (!PEM_read_bio_X509(certFile.get(), &x509, nullptr, nullptr)) {
|
||||
throw std::runtime_error("Couldn't read certificate file from disk. PEM_read_bio_X509(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
return x509;
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QX509::error.setError(1, exception.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QX509::error.setError(2, "Unknown error!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509::signCertificate - Function signs X509 certificate and returns signed X509 OpenSSL structure.
|
||||
/// \param endCertificate - Certificate that will be signed
|
||||
/// \param caCertificate - CA certificate that will sign end certificate
|
||||
/// \param caPrivateKey - CA certificate private key
|
||||
/// \param fileName - With that name certificate will be saved. Leave "", if don't need to save it
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened.
|
||||
///
|
||||
X509* QSimpleCrypto::QX509::signCertificate(X509* endCertificate, X509* caCertificate, EVP_PKEY* caPrivateKey, const QByteArray& fileName)
|
||||
{
|
||||
try {
|
||||
/* Set issuer to CA's subject. */
|
||||
if (!X509_set_issuer_name(endCertificate, X509_get_subject_name(caCertificate))) {
|
||||
throw std::runtime_error("Couldn't set issuer name for X509. X509_set_issuer_name(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Sign the certificate with key. */
|
||||
if (!X509_sign(endCertificate, caPrivateKey, EVP_sha256())) {
|
||||
throw std::runtime_error("Couldn't sign X509. X509_sign(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write certificate file on disk. If needed */
|
||||
if (!fileName.isEmpty()) {
|
||||
/* Initialize BIO */
|
||||
std::unique_ptr<BIO, void (*)(BIO*)> certFile { BIO_new_file(fileName.data(), "w+"), BIO_free_all };
|
||||
if (certFile == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize certFile. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write file on disk */
|
||||
if (!PEM_write_bio_X509(certFile.get(), endCertificate)) {
|
||||
throw std::runtime_error("Couldn't write certificate file on disk. PEM_write_bio_X509(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
}
|
||||
|
||||
return endCertificate;
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QX509::error.setError(1, exception.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QX509::error.setError(2, "Unknown error!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509::verifyCertificate - Function verifies X509 certificate and returns verified X509 OpenSSL structure.
|
||||
/// \param x509 - OpenSSL X509. That certificate will be verified.
|
||||
/// \param store - Trusted certificate must be added to X509_Store with 'addCertificateToStore(X509_STORE* ctx, X509* x509)'.
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened
|
||||
///
|
||||
X509* QSimpleCrypto::QX509::verifyCertificate(X509* x509, X509_STORE* store)
|
||||
{
|
||||
try {
|
||||
/* Initialize X509_STORE_CTX */
|
||||
std::unique_ptr<X509_STORE_CTX, void (*)(X509_STORE_CTX*)> ctx { X509_STORE_CTX_new(), X509_STORE_CTX_free };
|
||||
if (ctx == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set up CTX for a subsequent verification operation */
|
||||
if (!X509_STORE_CTX_init(ctx.get(), store, x509, nullptr)) {
|
||||
throw std::runtime_error("Couldn't initialize X509_STORE_CTX. X509_STORE_CTX_init(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Verify X509 */
|
||||
if (!X509_verify_cert(ctx.get())) {
|
||||
throw std::runtime_error("Couldn't verify cert. X509_verify_cert(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
return x509;
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QX509::error.setError(1, exception.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QX509::error.setError(2, "Unknown error!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509::generateSelfSignedCertificate - Function generatesand returns self signed X509.
|
||||
/// \param rsa - OpenSSL RSA.
|
||||
/// \param additionalData - Certificate information.
|
||||
/// \param certificateFileName - With that name certificate will be saved. Leave "", if don't need to save it.
|
||||
/// \param md - OpenSSL EVP_MD structure. Example: EVP_sha512().
|
||||
/// \param serialNumber - X509 certificate serial number.
|
||||
/// \param version - X509 certificate version.
|
||||
/// \param notBefore - X509 start date.
|
||||
/// \param notAfter - X509 end date.
|
||||
/// \return Returns OpenSSL X509 structure or nullptr, if error happened. Returned value must be cleaned up with 'X509_free' to avoid memory leak.
|
||||
///
|
||||
X509* QSimpleCrypto::QX509::generateSelfSignedCertificate(const RSA* rsa, const QMap<QByteArray, QByteArray>& additionalData,
|
||||
const QByteArray& certificateFileName, const EVP_MD* md,
|
||||
const long& serialNumber, const long& version,
|
||||
const long& notBefore, const long& notAfter)
|
||||
{
|
||||
try {
|
||||
/* Initialize X509 */
|
||||
X509* x509 = nullptr;
|
||||
if (!(x509 = X509_new())) {
|
||||
throw std::runtime_error("Couldn't initialize X509. X509_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Initialize EVP_PKEY */
|
||||
std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY*)> keyStore { EVP_PKEY_new(), EVP_PKEY_free };
|
||||
if (keyStore == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize keyStore. EVP_PKEY_new(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Sign rsa key */
|
||||
if (!EVP_PKEY_assign_RSA(keyStore.get(), rsa)) {
|
||||
throw std::runtime_error("Couldn't assign rsa. EVP_PKEY_assign_RSA(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set certificate serial number. */
|
||||
if (!ASN1_INTEGER_set(X509_get_serialNumber(x509), serialNumber)) {
|
||||
throw std::runtime_error("Couldn't set serial number. ASN1_INTEGER_set(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set certificate version */
|
||||
if (!X509_set_version(x509, version)) {
|
||||
throw std::runtime_error("Couldn't set version. X509_set_version(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Set certificate creation and expiration date */
|
||||
X509_gmtime_adj(X509_get_notBefore(x509), notBefore);
|
||||
X509_gmtime_adj(X509_get_notAfter(x509), notAfter);
|
||||
|
||||
/* Set certificate public key */
|
||||
if (!X509_set_pubkey(x509, keyStore.get())) {
|
||||
throw std::runtime_error("Couldn't set public key. X509_set_pubkey(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Initialize X509_NAME */
|
||||
X509_NAME* x509Name = X509_get_subject_name(x509);
|
||||
if (x509Name == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize X509_NAME. X509_NAME(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Add additional data to certificate */
|
||||
QMapIterator<QByteArray, QByteArray> certificateInformationList(additionalData);
|
||||
while (certificateInformationList.hasNext()) {
|
||||
/* Read next item in list */
|
||||
certificateInformationList.next();
|
||||
|
||||
/* Set additional data */
|
||||
if (!X509_NAME_add_entry_by_txt(x509Name, certificateInformationList.key().data(), MBSTRING_UTF8, reinterpret_cast<const unsigned char*>(certificateInformationList.value().data()), -1, -1, 0)) {
|
||||
throw std::runtime_error("Couldn't set additional information. X509_NAME_add_entry_by_txt(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Set certificate info */
|
||||
if (!X509_set_issuer_name(x509, x509Name)) {
|
||||
throw std::runtime_error("Couldn't set issuer name. X509_set_issuer_name(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Sign certificate */
|
||||
if (!X509_sign(x509, keyStore.get(), md)) {
|
||||
throw std::runtime_error("Couldn't sign X509. X509_sign(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write certificate file on disk. If needed */
|
||||
if (!certificateFileName.isEmpty()) {
|
||||
/* Initialize BIO */
|
||||
std::unique_ptr<BIO, void (*)(BIO*)> certFile { BIO_new_file(certificateFileName.data(), "w+"), BIO_free_all };
|
||||
if (certFile == nullptr) {
|
||||
throw std::runtime_error("Couldn't initialize certFile. BIO_new_file(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
|
||||
/* Write file on disk */
|
||||
if (!PEM_write_bio_X509(certFile.get(), x509)) {
|
||||
throw std::runtime_error("Couldn't write certificate file on disk. PEM_write_bio_X509(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
}
|
||||
}
|
||||
|
||||
return x509;
|
||||
} catch (std::exception& exception) {
|
||||
QSimpleCrypto::QX509::error.setError(1, exception.what());
|
||||
return nullptr;
|
||||
} catch (...) {
|
||||
QSimpleCrypto::QX509::error.setError(2, "Unknown error!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
176
client/3rd/QSimpleCrypto/sources/QX509Store.cpp
Normal file
176
client/3rd/QSimpleCrypto/sources/QX509Store.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
/**
|
||||
* 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/QX509Store.h"
|
||||
|
||||
QSimpleCrypto::QX509Store::QX509Store()
|
||||
{
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509::addCertificateToStore
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param x509 - OpenSSL X509.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::addCertificateToStore(X509_STORE* store, X509* x509)
|
||||
{
|
||||
if (!X509_STORE_add_cert(store, x509)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't add certificate to X509_STORE. X509_STORE_add_cert(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::addLookup
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param method - OpenSSL X509_LOOKUP_METHOD. Example: X509_LOOKUP_file.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::addLookup(X509_STORE* store, X509_LOOKUP_METHOD* method)
|
||||
{
|
||||
if (!X509_STORE_add_lookup(store, method)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't add lookup to X509_STORE. X509_STORE_add_lookup(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::setCertificateDepth
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param depth - That is the maximum number of untrusted CA certificates that can appear in a chain. Example: 0.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::setDepth(X509_STORE* store, const int& depth)
|
||||
{
|
||||
if (!X509_STORE_set_depth(store, depth)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set depth for X509_STORE. X509_STORE_set_depth(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::setFlag
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param flag - The verification flags consists of zero or more of the following flags ored together. Example: X509_V_FLAG_CRL_CHECK.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::setFlag(X509_STORE* store, const unsigned long& flag)
|
||||
{
|
||||
if (!X509_STORE_set_flags(store, flag)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set flag for X509_STORE. X509_STORE_set_flags(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::setFlag
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param purpose - Verification purpose in param to purpose. Example: X509_PURPOSE_ANY.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::setPurpose(X509_STORE* store, const int& purpose)
|
||||
{
|
||||
if (!X509_STORE_set_purpose(store, purpose)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set purpose for X509_STORE. X509_STORE_set_purpose(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::setTrust
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param trust - Trust Level. Example: X509_TRUST_SSL_SERVER.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::setTrust(X509_STORE* store, const int& trust)
|
||||
{
|
||||
if (!X509_STORE_set_trust(store, trust)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set trust for X509_STORE. X509_STORE_set_trust(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::setDefaultPaths
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::setDefaultPaths(X509_STORE* store)
|
||||
{
|
||||
if (!X509_STORE_set_default_paths(store)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't set default paths for X509_STORE. X509_STORE_set_default_paths(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::loadLocations
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param fileName - File name. Example: "caCertificate.pem".
|
||||
/// \param dirPath - Path to file. Example: "path/To/File".
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::loadLocations(X509_STORE* store, const QByteArray& fileName, const QByteArray& dirPath)
|
||||
{
|
||||
if (!X509_STORE_load_locations(store, fileName, dirPath)) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't load locations for X509_STORE. X509_STORE_load_locations(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::loadLocations
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param file - Qt QFile that will be loaded.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::loadLocations(X509_STORE* store, const QFile& file)
|
||||
{
|
||||
/* Initialize QFileInfo to read information about file */
|
||||
QFileInfo info(file);
|
||||
|
||||
if (!X509_STORE_load_locations(store, info.fileName().toLocal8Bit(), info.absoluteDir().path().toLocal8Bit())) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't load locations for X509_STORE. X509_STORE_load_locations(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief QSimpleCrypto::QX509Store::loadLocations
|
||||
/// \param store - OpenSSL X509_STORE.
|
||||
/// \param fileInfo - Qt QFileInfo.
|
||||
/// \return Returns 'true' on success and 'false', if error happened.
|
||||
///
|
||||
bool QSimpleCrypto::QX509Store::loadLocations(X509_STORE* store, const QFileInfo& fileInfo)
|
||||
{
|
||||
if (!X509_STORE_load_locations(store, fileInfo.fileName().toLocal8Bit(), fileInfo.absoluteDir().path().toLocal8Bit())) {
|
||||
QSimpleCrypto::QX509Store::error.setError(1, "Couldn't load locations for X509_STORE. X509_STORE_load_locations(). Error: " + QByteArray(ERR_error_string(ERR_get_error(), nullptr)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -16,7 +16,9 @@ include("3rd/QtSsh/src/botan/botan.pri")
|
|||
!android:!ios:include("3rd/SingleApplication/singleapplication.pri")
|
||||
include ("3rd/SortFilterProxyModel/SortFilterProxyModel.pri")
|
||||
include("3rd/qzxing/src/QZXing-components.pri")
|
||||
include("3rd/QSimpleCrypto/QSimpleCrypto.pri")
|
||||
|
||||
INCLUDEPATH += $$PWD/3rd/QSimpleCrypto/include
|
||||
INCLUDEPATH += $$PWD/3rd/OpenSSL/include
|
||||
DEPENDPATH += $$PWD/3rd/OpenSSL/include
|
||||
|
||||
|
@ -37,7 +39,6 @@ HEADERS += \
|
|||
core/servercontroller.h \
|
||||
debug.h \
|
||||
defines.h \
|
||||
encryption_helper.h \
|
||||
managementserver.h \
|
||||
platforms/ios/MobileUtils.h \
|
||||
platforms/linux/leakdetector.h \
|
||||
|
@ -96,7 +97,6 @@ SOURCES += \
|
|||
core/server_defs.cpp \
|
||||
core/servercontroller.cpp \
|
||||
debug.cpp \
|
||||
encryption_helper.cpp \
|
||||
main.cpp \
|
||||
managementserver.cpp \
|
||||
platforms/ios/MobileUtils.cpp \
|
||||
|
@ -169,7 +169,6 @@ win32 {
|
|||
-lshlwapi \
|
||||
-liphlpapi \
|
||||
-lws2_32 \
|
||||
-liphlpapi \
|
||||
-lgdi32
|
||||
|
||||
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
#include "encryption_helper.h"
|
||||
|
||||
#include <QTextStream>
|
||||
#include <QVariantMap>
|
||||
#include <QDebug>
|
||||
|
||||
#include "openssl/evp.h"
|
||||
|
||||
int gcm_encrypt(const char *plaintext, int plaintext_len,
|
||||
const char *key, const char *iv, int iv_len,
|
||||
char *ciphertext)
|
||||
{
|
||||
return gcm_encrypt((uchar*)plaintext, plaintext_len,
|
||||
(uchar*)key, (uchar*)iv, iv_len,
|
||||
(uchar*)ciphertext);
|
||||
}
|
||||
|
||||
int gcm_decrypt(const char *ciphertext, int ciphertext_len,
|
||||
const char *key,
|
||||
const char *iv, int iv_len,
|
||||
char *plaintext)
|
||||
{
|
||||
return gcm_decrypt((uchar*)ciphertext, ciphertext_len,
|
||||
(uchar*)key, (uchar*)iv, iv_len,
|
||||
(uchar*)plaintext);
|
||||
}
|
||||
|
||||
void handleErrors() {
|
||||
qDebug() << "handleErrors";
|
||||
}
|
||||
|
||||
int generate_key_and_iv(unsigned char *iv, unsigned char *key) {
|
||||
// unsigned char key[32];
|
||||
// unsigned char iv[16];
|
||||
// EVP_BytesToKey(EVP_aes_256_gcm(), EVP_md5(),
|
||||
// NULL,
|
||||
// key_file_buf, key_size, 1, // const unsigned char *data, int datal, int count,
|
||||
// key, iv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gcm_encrypt(const unsigned char *plaintext, int plaintext_len,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int iv_len,
|
||||
unsigned char *ciphertext)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len;
|
||||
int ciphertext_len;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if(!(ctx = EVP_CIPHER_CTX_new()))
|
||||
handleErrors();
|
||||
|
||||
/* Initialise the encryption operation. */
|
||||
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
|
||||
handleErrors();
|
||||
|
||||
/*
|
||||
* Set IV length if default 12 bytes (96 bits) is not appropriate
|
||||
*/
|
||||
if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
|
||||
handleErrors();
|
||||
|
||||
/* Initialise key and IV */
|
||||
if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
|
||||
handleErrors();
|
||||
|
||||
/*
|
||||
* Provide the message to be encrypted, and obtain the encrypted output.
|
||||
* EVP_EncryptUpdate can be called multiple times if necessary
|
||||
*/
|
||||
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
|
||||
handleErrors();
|
||||
ciphertext_len = len;
|
||||
|
||||
/*
|
||||
* Finalise the encryption. Normally ciphertext bytes may be written at
|
||||
* this stage, but this does not occur in GCM mode
|
||||
*/
|
||||
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
|
||||
handleErrors();
|
||||
ciphertext_len += len;
|
||||
|
||||
/* Clean up */
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
return ciphertext_len;
|
||||
}
|
||||
|
||||
int gcm_decrypt(const unsigned char *ciphertext, int ciphertext_len,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int iv_len,
|
||||
unsigned char *plaintext)
|
||||
{
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len;
|
||||
int plaintext_len;
|
||||
int ret;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if(!(ctx = EVP_CIPHER_CTX_new()))
|
||||
handleErrors();
|
||||
|
||||
/* Initialise the decryption operation. */
|
||||
if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
|
||||
handleErrors();
|
||||
|
||||
/* Set IV length. Not necessary if this is 12 bytes (96 bits) */
|
||||
if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
|
||||
handleErrors();
|
||||
|
||||
/* Initialise key and IV */
|
||||
if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
|
||||
handleErrors();
|
||||
|
||||
/*
|
||||
* Provide the message to be decrypted, and obtain the plaintext output.
|
||||
* EVP_DecryptUpdate can be called multiple times if necessary
|
||||
*/
|
||||
if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
|
||||
handleErrors();
|
||||
plaintext_len = len;
|
||||
|
||||
/*
|
||||
* Finalise the decryption. A positive return value indicates success,
|
||||
* anything else is a failure - the plaintext is not trustworthy.
|
||||
*/
|
||||
ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
|
||||
|
||||
/* Clean up */
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
|
||||
if(ret > 0) {
|
||||
/* Success */
|
||||
plaintext_len += len;
|
||||
return plaintext_len;
|
||||
} else {
|
||||
/* Verify failed */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#ifndef ENCRYPTION_HELPER_H
|
||||
#define ENCRYPTION_HELPER_H
|
||||
|
||||
#include <QSettings>
|
||||
#include <QIODevice>
|
||||
|
||||
|
||||
|
||||
int gcm_encrypt(const char *plaintext, int plaintext_len,
|
||||
const char *key,
|
||||
const char *iv, int iv_len,
|
||||
char *ciphertext);
|
||||
|
||||
int gcm_decrypt(const char *ciphertext, int ciphertext_len,
|
||||
const char *key,
|
||||
const char *iv, int iv_len,
|
||||
char *plaintext);
|
||||
|
||||
|
||||
int gcm_encrypt(const unsigned char *plaintext, int plaintext_len,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int iv_len,
|
||||
unsigned char *ciphertext);
|
||||
|
||||
int gcm_decrypt(const unsigned char *ciphertext, int ciphertext_len,
|
||||
const unsigned char *key,
|
||||
const unsigned char *iv, int iv_len,
|
||||
unsigned char *plaintext);
|
||||
|
||||
|
||||
#endif // ENCRYPTION_HELPER_H
|
|
@ -1,35 +1,37 @@
|
|||
#include "secure_qsettings.h"
|
||||
#include "encryption_helper.h"
|
||||
#include "platforms/ios/MobileUtils.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include "utils.h"
|
||||
#include <QRandomGenerator>
|
||||
#include "QAead.h"
|
||||
#include "QBlockCipher.h"
|
||||
|
||||
SecureQSettings::SecureQSettings(const QString &organization, const QString &application, QObject *parent)
|
||||
: QObject{parent},
|
||||
m_setting(organization, application, parent),
|
||||
m_settings(organization, application, parent),
|
||||
encryptedKeys({"Servers/serversList"})
|
||||
{
|
||||
qDebug() << "SecureQSettings::SecureQSettings CTOR";
|
||||
// load keys from system key storage
|
||||
#ifdef Q_OS_IOS
|
||||
key = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsKeyTag).toUtf8());
|
||||
iv = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsIvTag).toUtf8());
|
||||
m_key = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsKeyTag).toUtf8());
|
||||
m_iv = QByteArray::fromBase64(MobileUtils::readFromKeychain(settingsIvTag).toUtf8());
|
||||
#endif
|
||||
key = "12345qwerty00000";
|
||||
iv = "000000000000000";
|
||||
|
||||
bool encrypted = m_setting.value("Conf/encrypted").toBool();
|
||||
bool encrypted = m_settings.value("Conf/encrypted").toBool();
|
||||
|
||||
// convert settings to encrypted
|
||||
// convert settings to encrypted for if updated to >= 2.1.0
|
||||
if (encryptionRequired() && ! encrypted) {
|
||||
for (const QString &key : m_setting.allKeys()) {
|
||||
for (const QString &key : m_settings.allKeys()) {
|
||||
if (encryptedKeys.contains(key)) {
|
||||
const QVariant &val = value(key);
|
||||
setValue(key, val);
|
||||
}
|
||||
}
|
||||
m_setting.setValue("Conf/encrypted", true);
|
||||
m_setting.sync();
|
||||
m_settings.setValue("Conf/encrypted", true);
|
||||
m_settings.sync();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,18 +41,36 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue
|
|||
return m_cache.value(key);
|
||||
}
|
||||
|
||||
if (!m_settings.contains(key)) return defaultValue;
|
||||
|
||||
QVariant retVal;
|
||||
if (encryptionRequired() && encryptedKeys.contains(key)) {
|
||||
if (!m_setting.contains(key)) return defaultValue;
|
||||
|
||||
QByteArray encryptedValue = m_setting.value(key).toByteArray();
|
||||
// check if value is not encrypted, v. < 2.0.x
|
||||
retVal = m_settings.value(key);
|
||||
if (retVal.isValid()) {
|
||||
if (retVal.userType() == QVariant::ByteArray &&
|
||||
retVal.toByteArray().mid(0, magicString.size()) == magicString) {
|
||||
|
||||
if (m_key.isEmpty() || m_iv.isEmpty()) {
|
||||
qCritical() << "SecureQSettings::setValue Decryption requested, but key is empty";
|
||||
return {};
|
||||
}
|
||||
|
||||
QByteArray encryptedValue = retVal.toByteArray().mid(magicString.size());
|
||||
|
||||
QByteArray decryptedValue = decryptText(encryptedValue);
|
||||
|
||||
QDataStream ds(&decryptedValue, QIODevice::ReadOnly);
|
||||
|
||||
ds >> retVal;
|
||||
|
||||
if (!retVal.isValid()) {
|
||||
qWarning() << "SecureQSettings::value settings decryption failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
retVal = m_setting.value(key, defaultValue);
|
||||
qWarning() << "SecureQSettings::value invalid QVariant value";
|
||||
retVal = QVariant();
|
||||
}
|
||||
|
||||
m_cache.insert(key, retVal);
|
||||
|
@ -61,6 +81,7 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue
|
|||
void SecureQSettings::setValue(const QString &key, const QVariant &value)
|
||||
{
|
||||
if (encryptionRequired() && encryptedKeys.contains(key)) {
|
||||
if (!m_key.isEmpty() && !m_iv.isEmpty()) {
|
||||
QByteArray decryptedValue;
|
||||
{
|
||||
QDataStream ds(&decryptedValue, QIODevice::WriteOnly);
|
||||
|
@ -68,10 +89,16 @@ void SecureQSettings::setValue(const QString &key, const QVariant &value)
|
|||
}
|
||||
|
||||
QByteArray encryptedValue = encryptText(decryptedValue);
|
||||
m_setting.setValue(key, encryptedValue);
|
||||
m_settings.setValue(key, magicString + encryptedValue);
|
||||
}
|
||||
else {
|
||||
m_setting.setValue(key, value);
|
||||
qCritical() << "SecureQSettings::setValue Encryption required, but key is empty";
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
m_settings.setValue(key, value);
|
||||
}
|
||||
|
||||
m_cache.insert(key, value);
|
||||
|
@ -80,7 +107,7 @@ void SecureQSettings::setValue(const QString &key, const QVariant &value)
|
|||
|
||||
void SecureQSettings::remove(const QString &key)
|
||||
{
|
||||
m_setting.remove(key);
|
||||
m_settings.remove(key);
|
||||
m_cache.remove(key);
|
||||
|
||||
sync();
|
||||
|
@ -88,13 +115,13 @@ void SecureQSettings::remove(const QString &key)
|
|||
|
||||
void SecureQSettings::sync()
|
||||
{
|
||||
m_setting.sync();
|
||||
m_settings.sync();
|
||||
}
|
||||
|
||||
QByteArray SecureQSettings::backupAppConfig() const
|
||||
{
|
||||
QMap<QString, QVariant> cfg;
|
||||
for (const QString &key : m_setting.allKeys()) {
|
||||
for (const QString &key : m_settings.allKeys()) {
|
||||
cfg.insert(key, value(key));
|
||||
}
|
||||
|
||||
|
@ -125,20 +152,16 @@ void SecureQSettings::restoreAppConfig(const QByteArray &base64Cfg)
|
|||
}
|
||||
|
||||
|
||||
QByteArray SecureQSettings::encryptText(const QByteArray& value) const {
|
||||
char cipherText[UINT16_MAX];
|
||||
int cipherTextSize = gcm_encrypt(value.constData(), value.size(),
|
||||
key.constData(), iv.constData(), iv_len, cipherText);
|
||||
|
||||
return QByteArray::fromRawData((const char *)cipherText, cipherTextSize);
|
||||
QByteArray SecureQSettings::encryptText(const QByteArray& value) const
|
||||
{
|
||||
QSimpleCrypto::QBlockCipher cipher;
|
||||
return cipher.encryptAesBlockCipher(value, m_key, m_iv);
|
||||
}
|
||||
|
||||
QByteArray SecureQSettings::decryptText(const QByteArray& ba) const {
|
||||
char decryptPlainText[UINT16_MAX];
|
||||
gcm_decrypt(ba.data(), ba.size(),
|
||||
key.constData(), iv.constData(), iv_len, decryptPlainText);
|
||||
|
||||
return QByteArray::fromRawData(decryptPlainText, ba.size());
|
||||
QByteArray SecureQSettings::decryptText(const QByteArray& ba) const
|
||||
{
|
||||
QSimpleCrypto::QBlockCipher cipher;
|
||||
return cipher.decryptAesBlockCipher(ba, m_key, m_iv);
|
||||
}
|
||||
|
||||
bool SecureQSettings::encryptionRequired() const
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
constexpr const char* settingsKeyTag = "settingsKeyTag";
|
||||
constexpr const char* settingsIvTag = "settingsIvTag";
|
||||
|
||||
|
||||
class SecureQSettings : public QObject
|
||||
{
|
||||
public:
|
||||
|
@ -26,15 +27,17 @@ public:
|
|||
bool encryptionRequired() const;
|
||||
|
||||
private:
|
||||
QSettings m_setting;
|
||||
QSettings m_settings;
|
||||
|
||||
mutable QMap<QString, QVariant> m_cache;
|
||||
|
||||
QStringList encryptedKeys; // encode only key listed here
|
||||
|
||||
QByteArray key;
|
||||
QByteArray iv;
|
||||
int iv_len {16};
|
||||
QByteArray m_key;
|
||||
QByteArray m_iv;
|
||||
|
||||
const QByteArray magicString { "EncData" }; // Magic keyword used for mark encrypted QByteArray
|
||||
|
||||
};
|
||||
|
||||
#endif // SECUREQSETTINGS_H
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
const char Settings::cloudFlareNs1[] = "1.1.1.1";
|
||||
const char Settings::cloudFlareNs2[] = "1.0.0.1";
|
||||
|
||||
//SecureFormat Settings::m_secureFormat;
|
||||
|
||||
Settings::Settings(QObject* parent) :
|
||||
QObject(parent),
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include "core/defs.h"
|
||||
#include "containers/containers_defs.h"
|
||||
#include "encryption_helper.h"
|
||||
#include "secure_qsettings.h"
|
||||
|
||||
using namespace amnezia;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue