From bc48851164681a29df94e4c174d804fd0679abba Mon Sep 17 00:00:00 2001 From: Andrei Yankovich Date: Fri, 21 Jul 2023 21:12:59 +0300 Subject: [PATCH] Move to easyssl (#65) * update QuasarApp * updat qusrapp lib * begin to add opensll 3 support * update links to ssl lib * added new depends (easyssl) * easyssl update * update easy ssl * update easy ssl * update easyssl * remove old code (x509) * update submodules --- .gitmodules | 3 + CMakeLists.txt | 10 +- HeartTests/tst_testprotockol.cpp | 5 - HeartTests/units/ecdsaauthtest.cpp | 100 ------- HeartTests/units/ecdsaauthtest.h | 27 -- src/CMakeLists.txt | 34 +-- src/heart.h | 3 +- src/public/abstractnode.cpp | 169 +----------- src/public/abstractnode.h | 35 +-- src/public/hcrypto/ecdsassl11.cpp | 253 ------------------ src/public/hcrypto/ecdsassl11.h | 64 ----- src/public/hcrypto/icrypto.cpp | 14 - src/public/hcrypto/icrypto.h | 65 ----- src/public/hcryptoFeatures/asynckeysauth.h | 231 ---------------- src/public/hcryptoFeatures/authecdsa.h | 31 --- src/public/hcryptoFeatures/ecdsasigner.h | 22 -- .../hcryptoFeatures/isignerdelegate.cpp | 47 ---- src/public/hcryptoFeatures/isignerdelegate.h | 83 ------ src/public/hcryptoFeatures/signer.h | 91 ------- submodules/QuasarAppLib | 2 +- submodules/easyssl | 1 + 21 files changed, 28 insertions(+), 1262 deletions(-) delete mode 100644 HeartTests/units/ecdsaauthtest.cpp delete mode 100644 HeartTests/units/ecdsaauthtest.h delete mode 100644 src/public/hcrypto/ecdsassl11.cpp delete mode 100644 src/public/hcrypto/ecdsassl11.h delete mode 100644 src/public/hcrypto/icrypto.cpp delete mode 100644 src/public/hcrypto/icrypto.h delete mode 100644 src/public/hcryptoFeatures/asynckeysauth.h delete mode 100644 src/public/hcryptoFeatures/authecdsa.h delete mode 100644 src/public/hcryptoFeatures/ecdsasigner.h delete mode 100644 src/public/hcryptoFeatures/isignerdelegate.cpp delete mode 100644 src/public/hcryptoFeatures/isignerdelegate.h delete mode 100644 src/public/hcryptoFeatures/signer.h create mode 160000 submodules/easyssl diff --git a/.gitmodules b/.gitmodules index d50a29e..fa882c1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "submodules/QuasarAppLib"] path = submodules/QuasarAppLib url = https://github.com/QuasarApp/QuasarAppLib.git +[submodule "submodules/easyssl"] + path = submodules/easyssl + url = https://github.com/QuasarApp/easyssl.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 53f7bd4..7ca3f97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ # of this license document, but changing it is not allowed. # -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.18) project(Heart) if(TARGET ${PROJECT_NAME}) @@ -51,6 +51,14 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network Sql Concurrent REQUIR add_subdirectory(submodules/QuasarAppLib) add_subdirectory(submodules/crc) + +if (HEART_SSL) + option(EASYSSL_TESTS "disable tests of the easyssl submodule " OFF) + option(EASYSSL_STATIC_SSL "disable tests of the easyssl submodule " ${HEART_STATIC_SSL}) + + add_subdirectory(submodules/easyssl) +endif() + add_subdirectory(src) if (HEART_TESTS) diff --git a/HeartTests/tst_testprotockol.cpp b/HeartTests/tst_testprotockol.cpp index 2a105d8..754dd29 100644 --- a/HeartTests/tst_testprotockol.cpp +++ b/HeartTests/tst_testprotockol.cpp @@ -11,7 +11,6 @@ #include "abstractnodetest.h" #include #include -#include #include #include @@ -35,10 +34,6 @@ private slots: TestCase(bigDataTest, BigDataTest); TestCase(shedullerTest, ShedullerTest); -#ifdef USE_HEART_SSL - TestCase(ecdsaAuthTest, ECDSAAuthTest); -#endif - TestCase(upgradeDataBaseTest, UpgradeDataBaseTest) TestCase(multiVersionTest, MultiVersionTest) diff --git a/HeartTests/units/ecdsaauthtest.cpp b/HeartTests/units/ecdsaauthtest.cpp deleted file mode 100644 index b88fcfe..0000000 --- a/HeartTests/units/ecdsaauthtest.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2022-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - -#include "ecdsaauthtest.h" -#include -#include -#include - -#ifdef USE_HEART_SSL - -/* - * test class - */ -class ECDSA: public QH::AuthECDSA { - -public: - ECDSA(const QByteArray &publicKey, const QByteArray &privKey) { - setPublicKey(publicKey); - _priv = privKey; - } - - // AsyncKeysAuth interface -protected: - QByteArray getPrivateKey() const override { - return _priv; - }; - -private: - QByteArray _priv; - -}; - -ECDSAAuthTest::ECDSAAuthTest() { - -} - -ECDSAAuthTest::~ECDSAAuthTest() { - -} - -void ECDSAAuthTest::test() { - // create a publick and private keys array. - QByteArray pub, priv; - QString userID; - - // make public and private keys. - QVERIFY(QH::AuthECDSA::makeKeys(pub, priv)); - - // make user id - QString userIDOfPubKey = QCryptographicHash::hash(pub, - QCryptographicHash::Sha256). - toBase64(QByteArray::Base64UrlEncoding); - - // check createed keys. should be larget then 0. - QVERIFY(pub.length() && priv.length()); - - // create test auth object using ecdsa algorithm - ECDSA edsa(pub, priv); - - // The terst object should be invalid because it is not prepared. - QVERIFY(!edsa.isValid()); - - // the authetication should be failed bacause ecdsa class is invalid. - QVERIFY(!edsa.auth(600, &userID)); - QVERIFY(userID.isEmpty()); - - // prepare an authentication object. - QVERIFY(edsa.prepare()); - // the prepared object should be valid. - QVERIFY(edsa.isValid()); - - // authentication should be finished successful because auth object contains prepared valid signature. - QVERIFY(edsa.auth(600, &userID)); - QVERIFY(userID == userIDOfPubKey); - - // forget user id before new auth - userID.clear(); - - // authentication should be failed because the time range is depricated. - QVERIFY(!edsa.auth(0, &userID)); - QVERIFY(userID.isEmpty()); - - // change subsribe time and try login. - edsa.setUnixTime(time(0) + 1); - - std::this_thread::sleep_for(std::chrono::seconds(1)); - - // should be failed because signature is different of the time. - QVERIFY(!edsa.auth(600, &userID)); - QVERIFY(userID.isEmpty()); - - - - -} -#endif diff --git a/HeartTests/units/ecdsaauthtest.h b/HeartTests/units/ecdsaauthtest.h deleted file mode 100644 index 4eaf62d..0000000 --- a/HeartTests/units/ecdsaauthtest.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2022-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - -#ifndef ECDSAAUTHTEST_H -#define ECDSAAUTHTEST_H - -#include "test.h" -#include "testutils.h" - -#ifdef USE_HEART_SSL - -class ECDSAAuthTest: public Test, protected TestUtils -{ -public: - ECDSAAuthTest(); - ~ECDSAAuthTest(); - - void test(); - -}; -#endif - -#endif // ECDSAAUTHTEST_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e8cd92..99f3f01 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,11 +30,7 @@ if (HEART_VALIDATE_PACKS) endif() set(SLL_DEFINE "WITHOUT_SSL") - if (HEART_SSL) - - list(APPEND CMAKE_FIND_ROOT_PATH "$ENV{OPENSSL_ROOT_DIR}") - find_package(OpenSSL 1.1.1 REQUIRED) set(SLL_DEFINE "USE_HEART_SSL") endif() @@ -45,8 +41,6 @@ file(GLOB SOURCE_CPP "public/*.cpp" "public/*.h" "public/*.qrc" "public/packages/*.cpp" "public/packages/*.h" "public/packages/*.qrc" "private/*.cpp" "private/*.h" "private/*.qrc" - "public/hcrypto/*.cpp" "public/hcrypto/*.h" "public/hcrypto/*.qrc" - "public/hcryptoFeatures/*.cpp" "public/hcryptoFeatures/*.h" "public/hcryptoFeatures/*.qrc" ) set(PUBLIC_INCUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") @@ -56,33 +50,9 @@ set(PRIVATE_INCUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/private") add_library(${PROJECT_NAME} ${SOURCE_CPP}) -target_link_libraries(${PROJECT_NAME} PUBLIC Qt::Core Qt::Network Qt::Sql Qt::Concurrent QuasarApp crc) +target_link_libraries(${PROJECT_NAME} PUBLIC Qt::Core Qt::Network Qt::Sql Qt::Concurrent QuasarApp crc ) if (HEART_SSL) - - if (HEART_STATIC_SSL) - - message("Use static ssl") - target_link_libraries(${PROJECT_NAME} PUBLIC libcrypto.a libssl.a) - - else() - - message("Use shared ssl ") - target_link_libraries(${PROJECT_NAME} PUBLIC OpenSSL::Crypto OpenSSL::SSL) - - - if (ANDROID) - set(OPENSSL_ROOT_PATH "$ENV{OPENSSL_ROOT_DIR}") - - set(ANDROID_EXTRA_LIBS - ${OPENSSL_ROOT_PATH}/lib/libcrypto_1_1.so - ${OPENSSL_ROOT_PATH}/lib/libssl_1_1.so - CACHE INTERNAL "") - - message(ANDROID_EXTRA_LIBS = ${ANDROID_EXTRA_LIBS}) - endif() - endif() - message("Use the OpenSSL libraries: ${OPENSSL_LIBRARIES}") - + target_link_libraries(${PROJECT_NAME} PUBLIC easyssl) endif() target_include_directories(${PROJECT_NAME} PUBLIC ${PUBLIC_INCUDE_DIR}) diff --git a/src/heart.h b/src/heart.h index 4c4f4fd..cfaba87 100644 --- a/src/heart.h +++ b/src/heart.h @@ -8,8 +8,7 @@ #ifndef NETWORKPROTOCOL_H #define NETWORKPROTOCOL_H -#include "package.h" -#include "abstractnode.h" +#include "heart_global.h" inline void initResources() { Q_INIT_RESOURCE(ProtockolResusces); } diff --git a/src/public/abstractnode.cpp b/src/public/abstractnode.cpp index 6729dba..1858d7b 100644 --- a/src/public/abstractnode.cpp +++ b/src/public/abstractnode.cpp @@ -17,12 +17,9 @@ #ifdef USE_HEART_SSL -#include -#include -#include -#include -#include #include +#include +#include #include #include @@ -329,166 +326,16 @@ QSslConfiguration AbstractNode::getSslConfig() const { return _ssl; } -bool AbstractNode::generateRSAforSSL(EVP_PKEY *pkey) const { - - if (!pkey) { - return false; - } - - //#if OPENSSL_VERSION_MAJOR >= 3 - - // EVP_PKEY_CTX *pctx = - // EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); - - // unsigned int primes = 3; - // unsigned int bits = 4096; - // OSSL_PARAM params[3]; - - // pkey = EVP_RSA_gen(4096); - - // EVP_PKEY_keygen_init(pctx); - - // params[0] = OSSL_PARAM_construct_uint("bits", &bits); - // params[1] = OSSL_PARAM_construct_uint("primes", &primes); - // params[2] = OSSL_PARAM_construct_end(); - // EVP_PKEY_CTX_set_params(pctx, params); - - - // EVP_PKEY_generate(pctx, &pkey); - // EVP_PKEY_CTX_free(pctx); - - //#else - BIGNUM * bn = BN_new(); - - int rc = BN_set_word(bn, RSA_F4); - - if (rc != 1) { - BN_free(bn); - return false; - } - - RSA * rsa = RSA_new(); - - if (!RSA_generate_key_ex(rsa, 2048, bn, nullptr)) { - return false; - } - - q_check_ptr(rsa); - if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) - return false; - //#endif - return true; -} - -bool AbstractNode::generateSslDataPrivate(const SslSrtData &data, QSslCertificate& r_srt, QSslKey& r_key) { - - EVP_PKEY *pkey = EVP_PKEY_new(); - - if (!generateRSAforSSL(pkey)) { - return false; - } - - X509 * x509 = nullptr; - X509_NAME * name = nullptr; - BIO * bp_public = nullptr, * bp_private = nullptr; - const char *buffer = nullptr; - int size; - - x509 = X509_new(); - q_check_ptr(x509); - ASN1_INTEGER_set(X509_get_serialNumber(x509), 1); - X509_gmtime_adj(X509_get_notBefore(x509), 0); // not before current time - X509_gmtime_adj(X509_get_notAfter(x509), data.endTime); // not after a year from this point - X509_set_pubkey(x509, pkey); - name = X509_get_subject_name(x509); - q_check_ptr(name); - - unsigned char *C = reinterpret_cast(data.country.toLatin1().data()); - X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, C, -1, -1, 0); - - unsigned char *O = reinterpret_cast(data.organization.toLatin1().data()); - X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, O, -1, -1, 0); - - unsigned char *CN = reinterpret_cast(data.commonName.toLatin1().data()); - X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, CN, -1, -1, 0); - - X509_set_issuer_name(x509, name); - X509_sign(x509, pkey, EVP_sha256()); - bp_private = BIO_new(BIO_s_mem()); - q_check_ptr(bp_private); - if(PEM_write_bio_PrivateKey(bp_private, pkey, nullptr, nullptr, 0, nullptr, nullptr) != 1) { - EVP_PKEY_free(pkey); - X509_free(x509); - BIO_free_all(bp_private); - qCritical("PEM_write_bio_PrivateKey"); - return false; - - } - - bp_public = BIO_new(BIO_s_mem()); - q_check_ptr(bp_public); - if(PEM_write_bio_X509(bp_public, x509) != 1){ - EVP_PKEY_free(pkey); - X509_free(x509); - BIO_free_all(bp_public); - BIO_free_all(bp_private); - qCritical("PEM_write_bio_PrivateKey"); - return false; - - } - - size = static_cast(BIO_get_mem_data(bp_public, &buffer)); - q_check_ptr(buffer); - - r_srt = QSslCertificate(QByteArray(buffer, size)); - - if(r_srt.isNull()) { - EVP_PKEY_free(pkey); - X509_free(x509); - BIO_free_all(bp_public); - BIO_free_all(bp_private); - qCritical("Failed to generate a random client certificate"); - return false; - - } - - size = static_cast(BIO_get_mem_data(bp_private, &buffer)); - q_check_ptr(buffer); - r_key = QSslKey(QByteArray(buffer, size), QSsl::Rsa); - if(r_key.isNull()) { - EVP_PKEY_free(pkey); - X509_free(x509); - BIO_free_all(bp_public); - BIO_free_all(bp_private); - qCritical("Failed to generate a random private key"); - return false; - - } - - EVP_PKEY_free(pkey); // this will also free the rsa key - X509_free(x509); - BIO_free_all(bp_public); - BIO_free_all(bp_private); - - return true; -} - -QSslConfiguration AbstractNode::selfSignedSslConfiguration(const SslSrtData & sslData) { +QSslConfiguration AbstractNode::selfSignedSslConfiguration(const EasySSL::SslSrtData &sslData) { QSslConfiguration res = QSslConfiguration::defaultConfiguration(); QSslKey pkey; QSslCertificate crt; - if (!generateSslDataPrivate(sslData, crt, pkey)) { - - QuasarAppUtils::Params::log("fail to create ssl certificate. node svitch to InitFromSystem mode", - QuasarAppUtils::Warning); - - return res; - } - - res.setPrivateKey(pkey); - res.setLocalCertificate(crt); + EasySSL::X509 generator(QSharedPointer::create()); + EasySSL::SelfSignedSertificate certificate = generator.create(sslData); + res.setPrivateKey(certificate.key); + res.setLocalCertificate(certificate.crt); res.setPeerVerifyMode(QSslSocket::VerifyNone); return res; @@ -538,7 +385,7 @@ void AbstractNode::setIgnoreSslErrors(const QList &newIgnoreSslErrors _ignoreSslErrors = newIgnoreSslErrors; }; -bool AbstractNode::useSelfSignedSslConfiguration(const SslSrtData &crtData) { +bool AbstractNode::useSelfSignedSslConfiguration(const EasySSL::SslSrtData &crtData) { if (isListening()) { return false; diff --git a/src/public/abstractnode.h b/src/public/abstractnode.h index aa0fd7f..e1727fe 100644 --- a/src/public/abstractnode.h +++ b/src/public/abstractnode.h @@ -13,8 +13,8 @@ #include "ping.h" #ifdef USE_HEART_SSL -#include #include +#include #endif #include @@ -77,19 +77,6 @@ enum class AddNodeError { RegisterSocketFailed }; -#ifdef USE_HEART_SSL -/** - * @brief The SslSrtData struct This structure contains base information for generate self signed ssl certefication. - * If you want change selfSigned certificate then use method AbstractNode::useSelfSignedSslConfiguration. - */ -struct SslSrtData { - QString country = "BY"; - QString organization = "QuasarApp"; - QString commonName = ""; - long long endTime = 31536000L; //1 year -}; -#endif - #define CRITICAL_ERROOR -50 #define LOGICK_ERROOR -20 #define REQUEST_ERROR -5 @@ -456,28 +443,12 @@ protected: */ void setIgnoreSslErrors(const QList &newIgnoreSslErrors); - /** - * @brief generateRSAforSSL This method generate ssl rsa pair keys for using in selfsigned cetificate. - * By default generate RSA 2048, if you want change algorithm or keys size then override this method. - * @param pkey This is openssl pointer to RSA pair key. - * @return True if keys generated successful. - */ - virtual bool generateRSAforSSL(EVP_PKEY* pkey) const; - /** - * @brief generateSslDataPrivate This method generate a ssl certificate and a ssl keys using The SslSrtData structure. - * @param data The data for generate a selfSigned certificate. - * @param r_srt This is return value of a certivicate. - * @param r_key - This is return value of private ssl key. - * @return True if generate the selfSigned certificate finished succesful. - */ - virtual bool generateSslDataPrivate(const SslSrtData& data, QSslCertificate& r_srt, QSslKey& r_key); - /** * @brief selfSignedSslConfiguration This method create a new ssl configuration with selfsigned certificates. * @param data This is data for generate selfsigned certification for more information see SslSrtData structure. * @return The new selfsigned ssl configuration. */ - virtual QSslConfiguration selfSignedSslConfiguration( const SslSrtData& data = {}); + virtual QSslConfiguration selfSignedSslConfiguration( const EasySSL::SslSrtData& data = {}); #endif /** @@ -562,7 +533,7 @@ protected: * @param crtData - This is data for generation a new self signed certification. * @return result of change node ssl configuration. */ - bool useSelfSignedSslConfiguration(const SslSrtData& crtData); + bool useSelfSignedSslConfiguration(const EasySSL::SslSrtData& crtData); /** * @brief useSystemSslConfiguration This method reconfigure current node to use sslConfig. diff --git a/src/public/hcrypto/ecdsassl11.cpp b/src/public/hcrypto/ecdsassl11.cpp deleted file mode 100644 index 5400a42..0000000 --- a/src/public/hcrypto/ecdsassl11.cpp +++ /dev/null @@ -1,253 +0,0 @@ -//# -//# Copyright (C) 2021-2023 QuasarApp. -//# Distributed under the GPLv3 software license, see the accompanying -//# Everyone is permitted to copy and distribute verbatim copies -//# of this license document, but changing it is not allowed. -//# - - -#include "ecdsassl11.h" - -#ifdef USE_HEART_SSL - -#include // for ECDSA_do_sign, ECDSA_do_verify -#include // for NID_secp192k1 -#include -#include - -#include -#include -#include -#include -#include - -namespace QH { - -ECDSASSL11::ECDSASSL11() { - -} - -void printlastOpenSSlError() { - int error = ERR_get_error(); - char buffer[256]; - ERR_error_string(error, buffer); - QuasarAppUtils::Params::log(QString("openssl: %0").arg(buffer), - QuasarAppUtils::Error); -} - -QByteArray bignumToArray(const BIGNUM* num) { - int length = BN_bn2mpi(num, nullptr); - QVector data(length); - BN_bn2mpi(num, data.data()); - QByteArray result; - result.insert(0, reinterpret_cast(data.data()), data.length()); - return result; -} - -BIGNUM* bignumFromArray(const QByteArray& array) { - auto d = reinterpret_cast(array.data()); - BIGNUM* result = BN_mpi2bn(d, - array.length(), nullptr); - if (!result) { - printlastOpenSSlError(); - } - - return result; -} - -QByteArray extractPrivateKey(EC_KEY* ec_key) { - const BIGNUM* ec_priv = EC_KEY_get0_private_key(ec_key); - return bignumToArray(ec_priv); -} - -QByteArray extractPublicKey(EC_KEY* key, EC_GROUP* group) { - - QByteArray data; - point_conversion_form_t form = EC_GROUP_get_point_conversion_form(group); - - unsigned char* pub_key_buffer; - size_t length = EC_KEY_key2buf(key, form, &pub_key_buffer, nullptr); - - if (length <= 0) { - printlastOpenSSlError(); - return {}; - } - - data.insert(0, reinterpret_cast(pub_key_buffer), length); - - OPENSSL_free(pub_key_buffer); - - return data; -} - -bool ECDSASSL11::makeKeys(QByteArray &pubKey, QByteArray &privKey) { - - EC_KEY *eckey= nullptr; - EC_GROUP *ecgroup = nullptr; - - if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) { - return false; - } - - if (!EC_KEY_generate_key(eckey)) { - printlastOpenSSlError(); - EC_GROUP_free(ecgroup); - EC_KEY_free(eckey); - return false; - } - - pubKey = extractPublicKey(eckey, ecgroup); - privKey = extractPrivateKey(eckey); - - return pubKey.length() && privKey.length(); -} - -QByteArray ECDSASSL11::signMessage(const QByteArray &inputData, - const QByteArray &key) const { - - EC_KEY *eckey= nullptr; - EC_GROUP *ecgroup = nullptr; - - if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) { - return {}; - } - - auto hash = QCryptographicHash::hash(inputData, - QCryptographicHash::Sha256); - - BIGNUM* priv = bignumFromArray(key); - if (!EC_KEY_set_private_key(eckey, priv)) { - printlastOpenSSlError(); - EC_GROUP_free(ecgroup); - EC_KEY_free(eckey); - return {}; - }; - - ECDSA_SIG *signature = ECDSA_do_sign(reinterpret_cast(hash.data()), - hash.length(), eckey); - BN_free(priv); - EC_KEY_free(eckey); - EC_GROUP_free(ecgroup); - - if (!signature) { - printlastOpenSSlError(); - return {}; - } - - const BIGNUM * R, *S; - ECDSA_SIG_get0(signature, &R, &S); - - QByteArray result; - QDataStream stream(&result, QIODevice::WriteOnly); - - stream << bignumToArray(R); - stream << bignumToArray(S); - - ECDSA_SIG_free(signature); - - return result; -} - -bool ECDSASSL11::checkSign(const QByteArray &inputData, - const QByteArray &signature, - const QByteArray &key) const { - - - // extract signature from raw array - - BIGNUM * R, *S; - QDataStream stream(signature); - - QByteArray rR,rS; - stream >> rR; - stream >> rS; - R = bignumFromArray(rR); - S = bignumFromArray(rS); - - ECDSA_SIG *sig = ECDSA_SIG_new(); - ECDSA_SIG_set0(sig, R, S); - - auto hash = QCryptographicHash::hash(inputData, - QCryptographicHash::Sha256); - - - EC_KEY *eckey= nullptr; - EC_GROUP *ecgroup = nullptr; - - if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) { - ECDSA_SIG_free(sig); - return {}; - } - - - // extract key from raw array; - EC_POINT* ec_point = EC_POINT_new(ecgroup); - EC_POINT_oct2point(ecgroup, ec_point, - reinterpret_cast(key.data()), - key.length(), nullptr); - - EC_KEY_set_public_key(eckey, ec_point); - - - int verify_status = ECDSA_do_verify(reinterpret_cast(hash.data()), - hash.length(), sig, eckey); - - ECDSA_SIG_free(sig); - EC_POINT_free(ec_point); - - return verify_status == 1; - -} - -QByteArray ECDSASSL11::decript(const QByteArray &, const QByteArray &) { - return {}; -} - -QByteArray ECDSASSL11::encript(const QByteArray &, const QByteArray &) { - return {}; -} - -bool ECDSASSL11::prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) { - - // input data should be valid pointers to pointers of key and group objects. - if (!(eckey && ecgroup)) - return false; - - // input pointers should be nullptr; - if ((*eckey) || (*ecgroup)) - return false; - - auto free = [eckey, ecgroup] () { - if (*ecgroup) - EC_GROUP_free(*ecgroup); - - if (*eckey) - EC_KEY_free(*eckey); - }; - - *eckey = EC_KEY_new(); - if (!*eckey) { - printlastOpenSSlError(); - free(); - return false; - } - - *ecgroup = EC_GROUP_new_by_curve_name(NID_secp256k1); - - if (!*ecgroup) { - printlastOpenSSlError(); - free(); - return false; - } - - if (!EC_KEY_set_group(*eckey, *ecgroup)) { - printlastOpenSSlError(); - free(); - return false; - } - - return true; -} - -} -#endif diff --git a/src/public/hcrypto/ecdsassl11.h b/src/public/hcrypto/ecdsassl11.h deleted file mode 100644 index 8c06cb8..0000000 --- a/src/public/hcrypto/ecdsassl11.h +++ /dev/null @@ -1,64 +0,0 @@ -//# -//# Copyright (C) 2021-2023 QuasarApp. -//# Distributed under the GPLv3 software license, see the accompanying -//# Everyone is permitted to copy and distribute verbatim copies -//# of this license document, but changing it is not allowed. -//# - - -#ifndef QH_ECDSA_SSL_1_1_H -#define QH_ECDSA_SSL_1_1_H -#include "heart_global.h" - -#ifdef USE_HEART_SSL - -#include "icrypto.h" - -#include // for EC_GROUP_new_by_curve_name, EC_GROUP_free, EC_KEY_new, EC_KEY_set_group, EC_KEY_generate_key,EC_KEY_free - -namespace QH { - -/** - * @brief The ECDSASSL11 class is ecdsa implementation of the Async authentication. This implementation based on Openssl library. - * @note This class compatibility only with ssl 1.1 and ssl 3.0 (depricated fundtions). - */ -class HEARTSHARED_EXPORT ECDSASSL11: public QH::ICrypto -{ - -public: - ECDSASSL11(); - - /** - * @brief makeKeys This static method generate the public and private keys of the ECDSA. - * @param pubKey This is result public key. - * @param privKey This is result private key. - * @return true if keys generated successful. - */ - static bool makeKeys(QByteArray &pubKey, QByteArray &privKey); - -protected: - QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override; - bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override; - - /** - * @brief decript This method has empty implementation. - * @return empty array. - */ - QByteArray decript(const QByteArray &message, const QByteArray &key) override; - - /** - * @brief encript This method has empty implementation. - * @return empty array. - */ - QByteArray encript(const QByteArray &message, const QByteArray &key) override; - -private: - static bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup); - - }; - -} - -#endif - -#endif // QH_ECDSA_SSL_1_1_H diff --git a/src/public/hcrypto/icrypto.cpp b/src/public/hcrypto/icrypto.cpp deleted file mode 100644 index 4a2003c..0000000 --- a/src/public/hcrypto/icrypto.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2018-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - - -#include "icrypto.h" - - -namespace QH { - -} diff --git a/src/public/hcrypto/icrypto.h b/src/public/hcrypto/icrypto.h deleted file mode 100644 index 36f656d..0000000 --- a/src/public/hcrypto/icrypto.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2021-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - - -#ifndef I_CRYPTO_H -#define I_CRYPTO_H - -#include "heart_global.h" -#include - -namespace QH { - -/** - * @brief The ICrypto class This is base interface that provide encription functionality. - */ -class HEARTSHARED_EXPORT ICrypto -{ - -protected: - - /** - * @brief decript This method decript @a message using @a key. - * @param message This is encripted message that should be decripted. - * @param key This is key that will be used for decription for the @a message. - * @return decripted message or empty string if method not supported or decripted failed. - * @see IAsyncEncription::encript - */ - virtual QByteArray decript(const QByteArray& message, const QByteArray& key) = 0; - /** - * @brief decript This method encript @a message using @a key. - * @param message This is a message that should be decripted. - * @param key This is key that will be used for encription for the @a message. - * @return decripted message or empty string if method not supported or decripted failed. - * @see IAsyncEncription::encript - */ - virtual QByteArray encript(const QByteArray& message, const QByteArray& key) = 0; - - /** - * @brief signMessage This method should be sign the @a message using the @a key. - * @param message This is input data that should be signed. - * @param key This is a privete key for encription the @a message. - * @return signature data array. - * @see AsyncKeysAuth::descrupt - */ - virtual QByteArray signMessage(const QByteArray& message, const QByteArray& key) const = 0; - - /** - * @brief checkSign This method should be check signature of the @a message using the @a key. - * @param message This is input data that should be decripted. - * @param signature This is signature that will be checked for the @a message. - * @param key This is a public key for encription the @a inpputData. - * @return decripted data array. - * @see AsyncKeysAuth::encrypt - */ - virtual bool checkSign(const QByteArray& message, - const QByteArray& signature, - const QByteArray& key) const = 0; -}; - -} -#endif // I_CRYPTO_H diff --git a/src/public/hcryptoFeatures/asynckeysauth.h b/src/public/hcryptoFeatures/asynckeysauth.h deleted file mode 100644 index 9e4e59c..0000000 --- a/src/public/hcryptoFeatures/asynckeysauth.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2021-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - -#ifndef ASYNCKEYSAUTH_H -#define ASYNCKEYSAUTH_H - -#include -#include -#include - - -namespace QH { - -/** - * @brief The AsyncKeysAuth class is temaplate class for works with authorization of a pair of asynchronous keys - * This class contains base implementation for the authentication using async encription. The base encription alhorithm defined on the template argument **CryptoImplementation**. - * You can use any crypto alhorithm. - * - * ## Exampel of use: - * - * @code{cpp} - * #include - * - * using ECDSAAuth = AsyncKeysAuth; - * - * @endcode - * - * - * ### How to it works: - * - * * ----- - * - * ** Client Part ** - * - * * Client make a pair keys (public and private) = PUB and PRIV - * * Client get current unix time = U - * * Client make a data for signing = S - * S = SHA256{U + PUB} - * * Client make a signature SIG - * SIG = PRIV.signMessage(S) - * * Client prepare a auth request for server = R: - * R = {U,SIG,PUB} - * * Cleint send R to server - * - * * ----- - * - * ** Server Part ** - * - * * Server receive R from client. - * * Server compare U time with current unix time. - * * If the diferrence more then allowed value then server reject an auth - * * Server make S value as a client - * * Server check SIG value and comapre it with S value - * * If message sign is valid then server accept an auth else reject. - * * After accept server create new user with ID = sha256(PUB) or - * if user alredy exits make them as a logined user. - * - * @tparam CryptoImplementation This is internal implementaion of base encription functions. - * @see iCrypto class. - * - */ - -template -class AsyncKeysAuth: public CryptoImplementation -{ -public: - AsyncKeysAuth() { - - } - - ~AsyncKeysAuth() { - - } - - /** - * @brief auth This method make authentication and return true if the authentication finished successful else false. - * @brief retLoginedUserId This is logined user id in Base64UrlEncoding - * @return true if the authentication finished successful else false. - */ - bool auth(int allowedTimeRangeSec, QString* retLoginedUserId) const { - - int diff = time(0) - _unixTime; - - if (diff < 0) { - return false; - } - - if (diff >= allowedTimeRangeSec) { - return false; - } - - QByteArray data = _publicKey; - data.insert(0, reinterpret_cast(&_unixTime), - sizeof(_unixTime)); - - bool result = checkSign(data, _signature, _publicKey); - - if (result && retLoginedUserId) { - *retLoginedUserId = getUserId(); - } - - return result; - } - - /** - * @brief prepare This method will generate signature for autentication of client. Please inboke this method before send request to server. - * @return true if signature generated sucessuful. - */ - bool prepare() { - _unixTime = time(0); - - QByteArray data = _publicKey; - data.insert(0, reinterpret_cast(&_unixTime), - sizeof(_unixTime)); - - setSignature(signMessage(data, getPrivateKey())); - - return isValid(); - } - - /** - * @brief unixTime This method return unix time that client added for authentication. - * @return unix time that client added for authentication. - * @see AsyncKeysAuth::setUnixTime - */ - unsigned int unixTime() const { - return _unixTime; - } - - /** - * @brief setUnixTime This method sets new value of the unixTime propertye. - * @param newUnixTime This is new unix time value. Unix time sets in secunds from 1970 year - */ - void setUnixTime(unsigned int newUnixTime) { - _unixTime = newUnixTime; - } - - /** - * @brief signature This method return signature array. - * @return signature array. - * @see AsyncKeysAuth::setSignature - */ - const QByteArray &signature() const { - return _signature; - } - - /** - * @brief isValid this method check this ibject to valid. - * @return return true if object contains valid signature else false. - * @note Invoke the AsyncKeysAuth::prepare method before check valid of object. All object that not be preparred is invalid. - */ - bool isValid() const { - return _publicKey.size() && _signature.size() && _unixTime; - } - - /** - * @brief getUserId This method return user id that generated from the public key. - * @note This function works slow, because this object does not contain ID of user. The user ID will be generated every invoke of this function - * @return user ID. - */ - QString getUserId() const { - return QCryptographicHash::hash(_publicKey, - QCryptographicHash::Sha256). - toBase64(QByteArray::Base64UrlEncoding); - } - - - /** - * @brief publicKey This method return public key that client added for authentication. - * @note The @a publicKey will be used forcreate user id. - * @return public key that client added for authentication. - * @see AsyncKeysAuth::setPublicKey - */ - const QByteArray &publicKey() const { - return _publicKey; - } - - /** - * @brief setPublicKey This method sets new public key for authentication. - * @param newPublicKey Thiy is new key. - * @see AsyncKeysAuth::publicKey - */ - void setPublicKey(const QByteArray &newPublicKey) { - _publicKey = newPublicKey; - } - -protected: - - QByteArray decript(const QByteArray &message, const QByteArray &key) override { - return CryptoImplementation::decript(message, key); - }; - - QByteArray encript(const QByteArray &message, const QByteArray &key) override { - return CryptoImplementation::encript(message, key); - }; - - QByteArray signMessage(const QByteArray &message, const QByteArray &key) const override { - return CryptoImplementation::signMessage(message, key); - }; - - bool checkSign(const QByteArray &message, const QByteArray &signature, const QByteArray &key) const override { - return CryptoImplementation::checkSign(message, signature, key); - }; - - /** - * @brief getPrivateKey This method should be return private key for the public key that saved in this object. - * @return private key for the public key that saved in this object. - */ - virtual QByteArray getPrivateKey() const = 0; - - /** - * @brief setSignature Tihis is internal method for sets new signature value. - * @param newSignature new signature value. - * @note used in the - */ - void setSignature(const QByteArray &newSignature) { - _signature = newSignature; - } - - unsigned int _unixTime = 0; - QByteArray _signature; - QByteArray _publicKey; -}; - -} - -#endif // ASYNCKEYSAUTH_H diff --git a/src/public/hcryptoFeatures/authecdsa.h b/src/public/hcryptoFeatures/authecdsa.h deleted file mode 100644 index 2f909cf..0000000 --- a/src/public/hcryptoFeatures/authecdsa.h +++ /dev/null @@ -1,31 +0,0 @@ -//# -//# Copyright (C) 2021-2023 QuasarApp. -//# Distributed under the GPLv3 software license, see the accompanying -//# Everyone is permitted to copy and distribute verbatim copies -//# of this license document, but changing it is not allowed. -//# - - -#ifndef AUTHECDSA_H -#define AUTHECDSA_H -#include "heart_global.h" - -#ifdef USE_HEART_SSL - - -#include "hcrypto/ecdsassl11.h" - -#include "asynckeysauth.h" - - -namespace QH { - -/** - * @brief The AuthECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library. - */ -typedef AsyncKeysAuth AuthECDSA; - -} -#endif - -#endif // AUTHECDSA_H diff --git a/src/public/hcryptoFeatures/ecdsasigner.h b/src/public/hcryptoFeatures/ecdsasigner.h deleted file mode 100644 index d4cab7a..0000000 --- a/src/public/hcryptoFeatures/ecdsasigner.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2021-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - -#ifndef ECDSASIGNER_H -#define ECDSASIGNER_H - -#include "signer.h" -#include "hcrypto/ecdsassl11.h" - -namespace QH { - -/** - * @brief The ECDSASigner class is ecdsa implementation of the Signer class. This implementation based on Openssl library. - */ -typedef Signer ECDSASigner; - -} -#endif // ECDSASIGNER_H diff --git a/src/public/hcryptoFeatures/isignerdelegate.cpp b/src/public/hcryptoFeatures/isignerdelegate.cpp deleted file mode 100644 index 7810003..0000000 --- a/src/public/hcryptoFeatures/isignerdelegate.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - -#include "isignerdelegate.h" - -namespace QH { - -ISignerDelegate::ISignerDelegate() { - -} - -const QByteArray &ISignerDelegate::getSignature() const { - return sign; -} - -void ISignerDelegate::setSignature(const QByteArray &newSignature) { - sign = newSignature; -} - -const QByteArray &ISignerDelegate::getHash() const { - return hash; - -} - -void ISignerDelegate::setHash(const QByteArray &newHash) { - hash = newHash; - -} - -QDataStream &ISignerDelegate::fromStream(QDataStream &stream) { - stream >> hash; - stream >> sign; - - return stream; -} - -QDataStream &ISignerDelegate::toStream(QDataStream &stream) const { - stream << hash; - stream << sign; - - return stream; -} -} diff --git a/src/public/hcryptoFeatures/isignerdelegate.h b/src/public/hcryptoFeatures/isignerdelegate.h deleted file mode 100644 index 13e2882..0000000 --- a/src/public/hcryptoFeatures/isignerdelegate.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2021-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - - -#ifndef ISIGNERDELEGATE_H -#define ISIGNERDELEGATE_H - -#include - - -namespace QH { - -/** - * @brief The ISignerDelegate class This is base class of signer delegate. - * The sisgner class will be invoke all delegate methods for control the input object that need to sign. - * @note This class contasin sign and hash fild and override the >> and << operators for QDataStream, - * so if you want to convert your object to bytes array don not forget invoke the ISignerDelegate::fromStream and ISignerDelegate::toStream methods. - * @see Signer - */ -class ISignerDelegate: public StreamBase -{ -public: - ISignerDelegate(); - - /** - * @brief getSignature This method return constant reference to the signature array. - * @return constant reference to the signature array. - */ - virtual const QByteArray &getSignature() const; - - /** - * @brief setSignature This method sets the new signature of this object. - * @param newSignature new signature value. - */ - virtual void setSignature(const QByteArray &newSignature); - - /** - * @brief getHash This method return constant reference to the hash array. - * @return constant reference to the signature array. - */ - virtual const QByteArray &getHash() const; - - /** - * @brief setHash This method sets the new hash sum of this object. - * @param newSignature new signature value. - */ - virtual void setHash(const QByteArray &newHash); - - /** - * @brief getPrivateKey This method should be return private key for the public key that saved in this object. - * @return private key for the public key that saved in this object. - */ - virtual const QByteArray& getPrivateKey() const = 0; - - /** - * @brief getPublicKey This method should be return public key for the private key that encrypted this object. - * @return public key for the private key that ecrypt this object. - */ - virtual const QByteArray& getPublicKey() const = 0; - - /** - * @brief getMessage This method should be return message that you want to sign. - * @return message that you want to sign. - */ - virtual const QByteArray getMessage() const = 0; - - // StreamBase interface -protected: - QDataStream &fromStream(QDataStream &stream) override; - QDataStream &toStream(QDataStream &stream) const override; - -private: - QByteArray hash; - QByteArray sign; - -}; - -} -#endif // ISIGNERDELEGATE_H diff --git a/src/public/hcryptoFeatures/signer.h b/src/public/hcryptoFeatures/signer.h deleted file mode 100644 index 8cd92bd..0000000 --- a/src/public/hcryptoFeatures/signer.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2021-2023 QuasarApp. - * Distributed under the lgplv3 software license, see the accompanying - * Everyone is permitted to copy and distribute verbatim copies - * of this license document, but changing it is not allowed. -*/ - - -#ifndef SIGNER_H -#define SIGNER_H - -#include -#include -#include -#include "isignerdelegate.h" -#include "qaservice.h" - -namespace QH { - -/** - * @brief The Signer class can sign and check the signature of the any childs classes of the ISignerDelegate class. - * - * **Exmaple of use** - * - * @code{cpp} - * #include - * #include - * - * class MyDelegate: public ISignerDelegate { - * // override all methods - * }; - * - * int main () { - * MyDelegate delegate; - * - * // sign your object - * QH::ECDSASigner::sign(&delegate); - * - * // check signature of the object - * QH::ECDSASigner::check(&delegate); - * } - * - * - * @endcode - * - * @note the MyDelegate class should be contains a public for check signature and a private for sign object keys - * @tparam CryptoImplementation This is internal implementaion of base encription functions. - * @see iCrypto class. - */ -template -class Signer: protected QuasarAppUtils::Service>, - protected CryptoImplementation -{ -public: - Signer() {}; - ~Signer() {}; - - /** - * @brief sign This is main method for signing of this object. - * @return true if the object signed sucessful - */ - static bool sign(ISignerDelegate* obj) { - - if (auto signer = Signer::autoInstance()) { - auto sign = signer->signMessage(obj->getMessage(), obj->getPrivateKey()); - - if (sign.size()) { - obj->setSignature(sign); - return true; - } - - } - - return false; - }; - - /** - * @brief check This method check signature of this object. - * @return true if the objec signed - */ - static bool check(const ISignerDelegate* obj) { - if (auto signer = Signer::autoInstance()) { - return signer->checkSign(obj->getMessage(), obj->signature(), obj->getPublicKey()); - } - - return false; - }; - -}; -} -#endif // SIGNER_H diff --git a/submodules/QuasarAppLib b/submodules/QuasarAppLib index 62c9d4e..53a6770 160000 --- a/submodules/QuasarAppLib +++ b/submodules/QuasarAppLib @@ -1 +1 @@ -Subproject commit 62c9d4e7c228647d67d77848ef90fe47e5039c22 +Subproject commit 53a67709ff90b544036cb90edbfe8cb1ded6dc0b diff --git a/submodules/easyssl b/submodules/easyssl new file mode 160000 index 0000000..83cea81 --- /dev/null +++ b/submodules/easyssl @@ -0,0 +1 @@ +Subproject commit 83cea813075c1837c0dafc3036596c9667a5d213