From 332acbdf7beddac3f8cc63b36bce7bb8480957b1 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 3 Apr 2022 17:54:36 +0300 Subject: [PATCH] big changes to cheat card app --- Heart/AbstractSpace/Diagrams/KeyStorage.svg | 878 ------------------ .../Diagrams/keystorageimplementation.qmodel | 544 ----------- Heart/AbstractSpace/abstractnode.h | 2 - Heart/AbstractSpace/asynckeysauth.cpp | 81 -- Heart/AbstractSpace/asynckeysauth.h | 160 +++- Heart/AbstractSpace/authecdsa.cpp | 235 ----- Heart/AbstractSpace/authecdsa.h | 29 +- Heart/AbstractSpace/cryptopairkeys.cpp | 81 -- Heart/AbstractSpace/cryptopairkeys.h | 90 -- Heart/AbstractSpace/hcrypto/ecdsa.cpp | 254 +++++ Heart/AbstractSpace/hcrypto/ecdsa.h | 65 ++ Heart/AbstractSpace/{ => hcrypto}/icrypto.cpp | 4 - Heart/AbstractSpace/hcrypto/icrypto.h | 65 ++ Heart/AbstractSpace/icrypto.h | 105 --- Heart/AbstractSpace/keystorage.cpp | 391 -------- Heart/AbstractSpace/keystorage.h | 266 ------ Heart/CMakeLists.txt | 1 + Heart/DataBaseSpace/databasenode.cpp | 1 - .../packages/abstractnetworkmember.cpp | 7 +- .../packages/abstractnetworkmember.h | 1 + Heart/DataBaseSpace/packages/dbobject.cpp | 9 +- Heart/DataBaseSpace/packages/dbobject.h | 23 +- Heart/DataBaseSpace/singleclient.cpp | 3 +- Heart/DataBaseSpace/sqldbwriter.cpp | 4 +- HeartTests/AbstractSpace/abstractnodetest.cpp | 1 - HeartTests/DataBaseSpace/basenodetest.cpp | 1 - .../templatedatabasenodeunittests.h | 2 +- 27 files changed, 529 insertions(+), 2774 deletions(-) delete mode 100644 Heart/AbstractSpace/Diagrams/KeyStorage.svg delete mode 100644 Heart/AbstractSpace/Diagrams/keystorageimplementation.qmodel delete mode 100644 Heart/AbstractSpace/cryptopairkeys.cpp delete mode 100644 Heart/AbstractSpace/cryptopairkeys.h create mode 100644 Heart/AbstractSpace/hcrypto/ecdsa.cpp create mode 100644 Heart/AbstractSpace/hcrypto/ecdsa.h rename Heart/AbstractSpace/{ => hcrypto}/icrypto.cpp (81%) create mode 100644 Heart/AbstractSpace/hcrypto/icrypto.h delete mode 100644 Heart/AbstractSpace/icrypto.h delete mode 100644 Heart/AbstractSpace/keystorage.cpp delete mode 100644 Heart/AbstractSpace/keystorage.h diff --git a/Heart/AbstractSpace/Diagrams/KeyStorage.svg b/Heart/AbstractSpace/Diagrams/KeyStorage.svg deleted file mode 100644 index 2592e66..0000000 --- a/Heart/AbstractSpace/Diagrams/KeyStorage.svg +++ /dev/null @@ -1,878 +0,0 @@ - - -Qt SVG Document -Generated with Qt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Storage Location - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeyData - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeyData2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeyData3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -KeyData3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Node (Server or -Client) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -QH - - - - - - - - - - - - -KeyStorage - - - - - - - - - - - - - - - - - - - - - -(from AbstractSpace) - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ReadAllData methods - - - - - - - - - - - - - - - - - - - - - -(from AbstractSpace) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -This method read all files from storage -locations. -Where a name of file it is key of DataKey. - - - - - - - - - - - - - - - - - - - - - diff --git a/Heart/AbstractSpace/Diagrams/keystorageimplementation.qmodel b/Heart/AbstractSpace/Diagrams/keystorageimplementation.qmodel deleted file mode 100644 index a989e1e..0000000 --- a/Heart/AbstractSpace/Diagrams/keystorageimplementation.qmodel +++ /dev/null @@ -1,544 +0,0 @@ - - - - {578fb64c-d647-45d7-9413-1a54b354db2b} - - - - - - - - {3cc6cd6f-0ce7-43b5-8a8c-1962b0207c79} - - - KeyStorageImplementation - - - - - - - {1ee7a90d-8a76-4fbd-9bd2-ef7a78f293e9} - - - - - - - - - - {1ee7a90d-8a76-4fbd-9bd2-ef7a78f293e9} - - - KeyStorageImplementation - - - - - - - - - - - - {73bb3bc5-3604-4108-9eb9-6322ee2c03a6} - - - {5bf04cca-9103-4df5-a5a6-42ca6a7478cd} - Storage Location - x:585;y:320 - x:-95;y:-100;w:190;h:200 - false - 0 - - - artifact - false - - - - - - - - - - - {63906c75-b844-49ff-a2d7-003d91396628} - - - {54a04999-4d1f-474d-b713-b41960caad2f} - KeyData - x:530;y:265 - x:-20;y:-30;w:40;h:60 - 0 - - - document - false - - - - - - - - - - - {4ba1d96e-4bb2-490f-9a2c-30f37cab8090} - - - {7bf70bc2-48c6-4a73-8c37-c4d74c2a471c} - KeyData2 - x:635;y:265 - x:-20;y:-30;w:40;h:60 - 0 - - - document - false - - - - - - - - - - - {f3c8b82c-2d10-4aab-bf2d-f0a773b1a214} - - - {272fa499-b8f6-4b5f-a65d-52e94fd19e75} - KeyData3 - x:530;y:355 - x:-20;y:-30;w:40;h:60 - 0 - - - document - false - - - - - - - - - - - {0a31881d-976f-49b4-84bc-6e829fde7524} - - - {41a62eef-b99a-4292-9a5e-6877f3822d74} - KeyData3 - x:635;y:355 - x:-20;y:-30;w:40;h:60 - 0 - - - document - false - - - - - - - - - - - {90e23bca-830b-4f04-9b79-d2b76aa7a942} - - - {2ccda0b5-00de-4d4c-b365-e045dc6f6f31} - Node (Server or Client) - x:235;y:290 - x:-175;y:-130;w:350;h:260 - false - 0 - true - - - node - false - - - - - - - - - - - {32b0ae69-b40c-426c-aaa8-34d737714611} - - - {962cbac6-7959-42e9-acd3-f26976cbe484} - AbstractSpace - KeyStorage - x:235;y:300 - x:-155;y:-95;w:310;h:190 - false - 0 - - - QH - - - - - - - - - - - {18d07b5f-7a24-4007-811a-800f28514869} - - - {58bd3970-0d20-48e4-ad00-e9b89ee16e8e} - {b11fad66-7c15-4a0c-90d7-fdb7c7b09d54} - {73bb3bc5-3604-4108-9eb9-6322ee2c03a6} - - - 2 - - - - - - - - - - - {b11fad66-7c15-4a0c-90d7-fdb7c7b09d54} - - - {7c08d894-d147-4b48-8829-6f3a50c45cd0} - AbstractSpace - ReadAllData methods - x:235;y:320 - x:-140;y:-50;w:280;h:100 - false - 0 - - - false - - - - - - - - - {ac8b121e-fdfc-41ae-bc0b-296e2658c1dc} - - - This method read all files from storage locations. -Where a name of file it is key of DataKey. - x:99;y:300 - x:0;y:0;w:270.125;h:57 - false - 3 - - - - - - 1600928388806 - General - - - - - - - - - - {5bf04cca-9103-4df5-a5a6-42ca6a7478cd} - - - - - - - - {5bf04cca-9103-4df5-a5a6-42ca6a7478cd} - - - Storage Location - - - false - artifact - - - - - - - - {b4753b9b-bb59-4797-8201-0e7f6cc3a09f} - - - - - - - - {b4753b9b-bb59-4797-8201-0e7f6cc3a09f} - - - Новый Document - - - false - document - - - - - - - - {54a04999-4d1f-474d-b713-b41960caad2f} - - - - - - - - {54a04999-4d1f-474d-b713-b41960caad2f} - - - KeyData - - - false - document - - - - - - - - {7bf70bc2-48c6-4a73-8c37-c4d74c2a471c} - - - - - - - - {7bf70bc2-48c6-4a73-8c37-c4d74c2a471c} - - - KeyData2 - - - false - document - - - - - - - - {272fa499-b8f6-4b5f-a65d-52e94fd19e75} - - - - - - - - {272fa499-b8f6-4b5f-a65d-52e94fd19e75} - - - KeyData3 - - - false - document - - - - - - - - {41a62eef-b99a-4292-9a5e-6877f3822d74} - - - - - - - - {41a62eef-b99a-4292-9a5e-6877f3822d74} - - - KeyData3 - - - false - document - - - - - - - - {2ccda0b5-00de-4d4c-b365-e045dc6f6f31} - - - - - - - - {2ccda0b5-00de-4d4c-b365-e045dc6f6f31} - - - Node (Server or Client) - - - false - node - - - - - - - - {d472d214-54c2-4045-b825-9a2ab109d69f} - - - - - - - - {d472d214-54c2-4045-b825-9a2ab109d69f} - 1 - - - AbstractSpace - - - - - - - {962cbac6-7959-42e9-acd3-f26976cbe484} - - - - - - - - {962cbac6-7959-42e9-acd3-f26976cbe484} - 1 - - - KeyStorage - - - QH - - - - - - - - {7c08d894-d147-4b48-8829-6f3a50c45cd0} - - - - - - - - {7c08d894-d147-4b48-8829-6f3a50c45cd0} - - - ReadAllData methods - - - - - - - {58bd3970-0d20-48e4-ad00-e9b89ee16e8e} - - - - - - - - {58bd3970-0d20-48e4-ad00-e9b89ee16e8e} - - - {7c08d894-d147-4b48-8829-6f3a50c45cd0} - {5bf04cca-9103-4df5-a5a6-42ca6a7478cd} - - - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Heart/AbstractSpace/abstractnode.h b/Heart/AbstractSpace/abstractnode.h index 14e1c6d..b3c96e8 100644 --- a/Heart/AbstractSpace/abstractnode.h +++ b/Heart/AbstractSpace/abstractnode.h @@ -27,8 +27,6 @@ #include "abstractdata.h" #include "workstate.h" #include "package.h" -#include "cryptopairkeys.h" -#include "icrypto.h" #include "heart_global.h" #include "packagemanager.h" #include "abstracterrorcodes.h" diff --git a/Heart/AbstractSpace/asynckeysauth.cpp b/Heart/AbstractSpace/asynckeysauth.cpp index 1c49de8..7ea9b75 100644 --- a/Heart/AbstractSpace/asynckeysauth.cpp +++ b/Heart/AbstractSpace/asynckeysauth.cpp @@ -6,85 +6,4 @@ */ #include "asynckeysauth.h" -#include "QCryptographicHash" -#include -#include -namespace QH { - -AsyncKeysAuth::AsyncKeysAuth() { - -} - -bool AsyncKeysAuth::auth(int allowedTimeRangeSec, QString* userId) 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 && userId) { - *userId = getUserId(); - } - - return result; -} - -bool AsyncKeysAuth::prepare() { - _unixTime = time(0); - - QByteArray data = _publicKey; - data.insert(0, reinterpret_cast(&_unixTime), - sizeof(_unixTime)); - - setSignature(signMessage(data, getPrivateKey())); - - return isValid(); -} - -unsigned int AsyncKeysAuth::unixTime() const { - return _unixTime; -} - -void AsyncKeysAuth::setUnixTime(unsigned int newUnixTime) { - _unixTime = newUnixTime; -} - -const QByteArray &AsyncKeysAuth::signature() const { - return _signature; -} - -const QByteArray &AsyncKeysAuth::publicKey() const { - return _publicKey; -} - -void AsyncKeysAuth::setPublicKey(const QByteArray &newPublicKey) { - _publicKey = newPublicKey; -} - -bool AsyncKeysAuth::isValid() const { - return _publicKey.size() && _signature.size() && _unixTime; -} - -QString AsyncKeysAuth::getUserId() const { - return QCryptographicHash::hash(_publicKey, - QCryptographicHash::Sha256). - toBase64(QByteArray::Base64UrlEncoding); -} - -void AsyncKeysAuth::setSignature(const QByteArray &newSignature) { - _signature = newSignature; -} - -} diff --git a/Heart/AbstractSpace/asynckeysauth.h b/Heart/AbstractSpace/asynckeysauth.h index ac57ae8..2925616 100644 --- a/Heart/AbstractSpace/asynckeysauth.h +++ b/Heart/AbstractSpace/asynckeysauth.h @@ -8,14 +8,29 @@ #ifndef ASYNCKEYSAUTH_H #define ASYNCKEYSAUTH_H -#include +#include +#include +#include #include "heart_global.h" +#include "hcrypto/icrypto.h" namespace QH { /** - * @brief The AsyncKeysAuth class is base class for works with authorization of a pair of asynchronous keys + * @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: * @@ -46,45 +61,115 @@ namespace QH { * * 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. * */ -class HEARTSHARED_EXPORT AsyncKeysAuth + +template +class HEARTSHARED_EXPORT AsyncKeysAuth: public CryptoImplementation { public: - AsyncKeysAuth(); + 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; + 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(); + 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; + 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); + void setUnixTime(unsigned int newUnixTime) { + _unixTime = newUnixTime; + } /** * @brief signature This method return signature array. * @return signature array. * @see AsyncKeysAuth::setSignature */ - const QByteArray &signature() const; + 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. @@ -92,49 +177,36 @@ public: * @return public key that client added for authentication. * @see AsyncKeysAuth::setPublicKey */ - const QByteArray &publicKey() const; + 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); - - /** - * @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; - - /** - * @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; + void setPublicKey(const QByteArray &newPublicKey) { + _publicKey = newPublicKey; + } protected: - /** - * @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; + QByteArray decript(const QByteArray &message, const QByteArray &key) override { + return CryptoImplementation::decript(message, key); + }; - /** - * @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; + 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. @@ -147,7 +219,9 @@ protected: * @param newSignature new signature value. * @note used in the */ - void setSignature(const QByteArray &newSignature); + void setSignature(const QByteArray &newSignature) { + _signature = newSignature; + } unsigned int _unixTime = 0; QByteArray _signature; diff --git a/Heart/AbstractSpace/authecdsa.cpp b/Heart/AbstractSpace/authecdsa.cpp index 8f7a938..f2d52ba 100644 --- a/Heart/AbstractSpace/authecdsa.cpp +++ b/Heart/AbstractSpace/authecdsa.cpp @@ -7,238 +7,3 @@ #include "authecdsa.h" - -#ifdef USE_HEART_SSL - -#include // for ECDSA_do_sign, ECDSA_do_verify -#include // for NID_secp192k1 -#include -#include - -#include -#include -#include -#include - -namespace QH { - -AuthECDSA::AuthECDSA() { - -} - -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 AuthECDSA::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 AuthECDSA::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 AuthECDSA::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; - -} - -bool AuthECDSA::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/Heart/AbstractSpace/authecdsa.h b/Heart/AbstractSpace/authecdsa.h index 92d45e6..93a2b6a 100644 --- a/Heart/AbstractSpace/authecdsa.h +++ b/Heart/AbstractSpace/authecdsa.h @@ -14,42 +14,19 @@ #include "abstractdata.h" +#include "hcrypto/ecdsa.h" + #include -#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 AuthECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library. */ -class HEARTSHARED_EXPORT AuthECDSA: public QH::AsyncKeysAuth -{ - -public: - AuthECDSA(); - - /** - * @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); - - // AsyncKeysAuth interface -protected: - QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override; - bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override; - -private: - static bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup); - -}; - +typedef AsyncKeysAuth AuthECDSA; } - #endif #endif // AUTHECDSA_H diff --git a/Heart/AbstractSpace/cryptopairkeys.cpp b/Heart/AbstractSpace/cryptopairkeys.cpp deleted file mode 100644 index 67933f5..0000000 --- a/Heart/AbstractSpace/cryptopairkeys.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2018-2022 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 "cryptopairkeys.h" - -#include -namespace QH { -CryptoPairKeys::CryptoPairKeys() { - -} - -CryptoPairKeys::CryptoPairKeys(const QByteArray &pubKey, const QByteArray &privKey) { - setPrivKey(privKey); - setPublicKey(pubKey); - setBits(privKey.size() * 8); -} - -bool CryptoPairKeys::isValid() const { - return _privKey.size() && _publicKey.size() && !(_bits % 8) && _bits > 1; -} - -QByteArray CryptoPairKeys::privKey() const { - return _privKey; -} - -void CryptoPairKeys::setPrivKey(const QByteArray &privKey) { - _privKey = privKey; -} - -QByteArray CryptoPairKeys::publicKey() const { - return _publicKey; -} - -void CryptoPairKeys::setPublicKey(const QByteArray &publicKey) { - _publicKey = publicKey; -} - -int CryptoPairKeys::bits() const { - return _bits; -} - -void CryptoPairKeys::setBits(int bits) { - _bits = bits; -} - -QDataStream &CryptoPairKeys::fromStream(QDataStream &stream) { - - stream >> _publicKey; - stream >> _privKey; - stream >> _bits; - - return stream; -} - -QDataStream &CryptoPairKeys::toStream(QDataStream &stream) const { - stream << _publicKey; - stream << _privKey; - stream << _bits; - - return stream; - -} - -bool operator ==(const CryptoPairKeys &left, const CryptoPairKeys &right) { - return !(left != right); -} - -bool operator !=(const CryptoPairKeys &left, const CryptoPairKeys &right) { - return left._privKey != right._privKey || left._publicKey != right._publicKey; -} - -uint qHash(const CryptoPairKeys &value) { - return qHash(value.privKey()); -} - -} diff --git a/Heart/AbstractSpace/cryptopairkeys.h b/Heart/AbstractSpace/cryptopairkeys.h deleted file mode 100644 index e3c7cf8..0000000 --- a/Heart/AbstractSpace/cryptopairkeys.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2018-2022 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 CRYPTOPAIRKEYS_H -#define CRYPTOPAIRKEYS_H - -#include "streambase.h" - - -namespace QH { - -/** - * @brief The CryptoPairKeys class contains pair keys. This is wraper for cripto graphick keys. - */ -class HEARTSHARED_EXPORT CryptoPairKeys: public StreamBase -{ -public: - CryptoPairKeys(); - CryptoPairKeys(const QByteArray& pubKey, const QByteArray& privKey); - - /** - * @brief isValid - This Method check an internal keys. - * @return true if this objeсt contains a valid pair keys. - */ - bool isValid() const; - - /** - * @brief privKey This method return private key of current keys pair. - * @return return byteArray of private key. - */ - QByteArray privKey() const; - - /** - * @brief setPrivKey This method set a private key for keys pair. - * @param privKey new byte array of private pair keys. - */ - void setPrivKey(const QByteArray &privKey); - - /** - * @brief publicKey This method return public key of array. - * @return publicKey of current key pair. - */ - QByteArray publicKey() const; - - /** - * @brief setPublicKey This method set new value of publickKey. - * @param publicKey new value of publicKey. - */ - void setPublicKey(const QByteArray &publicKey); - - /** - * @brief bits This method return size pair of crypto keys in bits. - * @return bits size of keys pair. - */ - int bits() const; - - /** - * @brief setBits This method sets new value of keys pair. - * @param bits This is new value of size keys. - */ - void setBits(int bits); - - friend bool operator != (const CryptoPairKeys& left, const CryptoPairKeys& right); - friend bool operator == (const CryptoPairKeys& left, const CryptoPairKeys& right); - - // StreamBase interface -protected: - QDataStream &fromStream(QDataStream &stream); - QDataStream &toStream(QDataStream &stream) const; - -private: - QByteArray _privKey; - QByteArray _publicKey; - - int _bits; -}; - -/** - * @brief qHash This functions calc crc32 hash code of CryptoPairKeys object. - * @param value - - * @return crc32 hash code. - */ - uint qHash(const CryptoPairKeys& value); -} -#endif // CRYPTOPAIRKEYS_H diff --git a/Heart/AbstractSpace/hcrypto/ecdsa.cpp b/Heart/AbstractSpace/hcrypto/ecdsa.cpp new file mode 100644 index 0000000..d7bea5d --- /dev/null +++ b/Heart/AbstractSpace/hcrypto/ecdsa.cpp @@ -0,0 +1,254 @@ +//# +//# Copyright (C) 2021-2022 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 "ecdsa.h" + +#ifdef USE_HEART_SSL + +#include // for ECDSA_do_sign, ECDSA_do_verify +#include // for NID_secp192k1 +#include +#include + +#include +#include +#include +#include + +namespace QH { + +ECDSA::ECDSA() { + +} + +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 ECDSA::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 ECDSA::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 ECDSA::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 ECDSA::decript(const QByteArray &message, const QByteArray &key) { + QuasarAppUtils::Params::log(""); + + return {}; +} + +QByteArray ECDSA::encript(const QByteArray &message, const QByteArray &key) { + return {}; +} + +bool ECDSA::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/Heart/AbstractSpace/hcrypto/ecdsa.h b/Heart/AbstractSpace/hcrypto/ecdsa.h new file mode 100644 index 0000000..d41b4ee --- /dev/null +++ b/Heart/AbstractSpace/hcrypto/ecdsa.h @@ -0,0 +1,65 @@ +//# +//# Copyright (C) 2021-2022 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_H +#define QH_ECDSA_H +#include "heart_global.h" + +#ifdef USE_HEART_SSL + + +#include "abstractdata.h" +#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 ECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library. + */ +class HEARTSHARED_EXPORT ECDSA: public QH::ICrypto +{ + +public: + ECDSA(); + + /** + * @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_H diff --git a/Heart/AbstractSpace/icrypto.cpp b/Heart/AbstractSpace/hcrypto/icrypto.cpp similarity index 81% rename from Heart/AbstractSpace/icrypto.cpp rename to Heart/AbstractSpace/hcrypto/icrypto.cpp index dd4d691..81c01ce 100644 --- a/Heart/AbstractSpace/icrypto.cpp +++ b/Heart/AbstractSpace/hcrypto/icrypto.cpp @@ -11,8 +11,4 @@ namespace QH { -ICrypto::ICrypto() = default; - -ICrypto::~ICrypto() = default; - } diff --git a/Heart/AbstractSpace/hcrypto/icrypto.h b/Heart/AbstractSpace/hcrypto/icrypto.h new file mode 100644 index 0000000..686a30b --- /dev/null +++ b/Heart/AbstractSpace/hcrypto/icrypto.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021-2022 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/Heart/AbstractSpace/icrypto.h b/Heart/AbstractSpace/icrypto.h deleted file mode 100644 index 22eb157..0000000 --- a/Heart/AbstractSpace/icrypto.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2018-2022 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 ICRYPTO_H -#define ICRYPTO_H - -#include -#include -#include "heart_global.h" -#include -#include -#include -#define RAND_KEY "" - -class QMutex; - -namespace QH { - -class CryptoPairKeys; - -/** - * @brief The ICrypto class provide cryptographic functionality. - * This is interface for decoration of KeyStorage classes. - */ -class HEARTSHARED_EXPORT ICrypto -{ - -public: - ICrypto(); - virtual ~ICrypto(); - - /** - * @brief isValid check crypto object is valid. - * @return true if the crypto object is valid. - */ - virtual bool isValid() const = 0; - - - /** - * @brief crypt This method crypt input data using public key. - * @param data This is pointer to data array for crypting. - * @note data as ben changed after call this method. - * @param publicKey This is key for crypting data. - * @return true if function finished successful. - */ - virtual bool crypt(QByteArray *data, const QByteArray& publicKey) = 0; - - /** - * @brief decrypt This method decrypt input data. - * @param cryptedData This is pointer to data array for decrypting. - * @note cryptedData has been changed after call this method. - * @param privateKey This is key for decrypting data message - * @return true if function finished successful. - */ - virtual bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey) = 0; - - /** - * @brief sign This method sign a input message using privateKey. - * @param data This is pointer to data array for signed. - * @note data has been changed after call this method. - * @param privateKey This is key for sign a message. - * @return true if function finished successful. - */ - virtual bool sign(QByteArray* data, const QByteArray& privateKey) = 0; - - /** - * @brief extractSign This method extract sign from signed byteArray. - * @param data - signed message. - * @return return array of sign. - */ - virtual QByteArray extractSign(const QByteArray& data) = 0; - - /** - * @brief concatSign This method make a concatenation between a message data and a sign of message. - * @param data This is message data. - * @param sign This is sign of message. - * @return signed message. - */ - virtual QByteArray concatSign(const QByteArray& data, const QByteArray& sign) = 0; - - /** - * @brief check This method validation signed message - * @param signedData This is array of signed data. - * @param publicKey This is public key for validation of message. - * @return true if function finished successful and signedData is valid. - */ - virtual bool check(const QByteArray& signedData, const QByteArray& publicKey) = 0; - - /** - * @brief generate This method is generate a new key pair. Default implementation do nothing. - * @note Override this method for create of new class with new keys type. - * @param genesis This is genesis bytes Array. if is possible add support generate keys pair from genesis data. - * @return crypto pair keys. - */ - virtual CryptoPairKeys generate(const QByteArray& genesis = {}) const = 0; - -}; - -} -#endif // CRYPTO_H diff --git a/Heart/AbstractSpace/keystorage.cpp b/Heart/AbstractSpace/keystorage.cpp deleted file mode 100644 index 62f4d03..0000000 --- a/Heart/AbstractSpace/keystorage.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2018-2022 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 "cryptopairkeys.h" -#include "icrypto.h" -#include "keystorage.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include "config.h" - -namespace QH { - -#define THE_CLASS(x) QString::fromLatin1(typeid(*x).name()) -#define VERSION_FILE "version" - -KeyStorage::KeyStorage(ICrypto * cryptoMethod) { - _keyPoolSizeMutex = new QMutex(); - _keysMutex = new QMutex(); - _taskMutex = new QMutex(); - - _cryptoMethod = cryptoMethod; - - assert(_cryptoMethod); -} - -KeyStorage::~KeyStorage() { - - stop(); - waitForThreadFinished(WAIT_TIME); - - if (!saveStorage()) { - QuasarAppUtils::Params::log("save keys to storae is failed!", - QuasarAppUtils::Error); - } - - delete _keyPoolSizeMutex; - delete _keysMutex; - delete _taskMutex; - delete _cryptoMethod; -} - -CryptoPairKeys KeyStorage::getNextPair(const QString &accsessKey, - const QByteArray& genesis, - int timeout) { - - if (!isInited() && genesis == RAND_KEY) { - QuasarAppUtils::Params::log("You want get the random crypto keys pair in a not initialized crypto object.", - QuasarAppUtils::Error); - return CryptoPairKeys{}; - } - - if (_keyPoolSize <= 0) { - return CryptoPairKeys{}; - } - - if (!genKey(accsessKey, genesis)) { - return {}; - } - - start(); - - if (!waitForGeneratekey(accsessKey, timeout)) { - return CryptoPairKeys{}; - } - - QMutexLocker locker(_keysMutex); - - return _keys.value(accsessKey, {}); -} - -int KeyStorage::getKeyPoolSize() const { - return _keyPoolSize; -} - -void KeyStorage::setKeyPoolSize(int keyPoolSize) { - _keyPoolSizeMutex->lock(); - _keyPoolSize = keyPoolSize; - _keyPoolSizeMutex->unlock(); - - start(); -} - -bool KeyStorage::isValid() const { - return isInited(); -} - -bool KeyStorage::isInited() const { - return _inited; -} - -bool KeyStorage::crypt(QByteArray *data, const QByteArray &publicKey) { - return _cryptoMethod->crypt(data, publicKey); -} - -bool KeyStorage::decrypt(QByteArray *cryptedData, const QByteArray &privateKey) { - return _cryptoMethod->decrypt(cryptedData, privateKey); -} - -bool KeyStorage::sign(QByteArray *data, const QByteArray &privateKey) { - return _cryptoMethod->sign(data, privateKey); -} - -QByteArray KeyStorage::extractSign(const QByteArray &data) { - return _cryptoMethod->extractSign(data); -} - -QByteArray KeyStorage::concatSign(const QByteArray &data, const QByteArray &sign) { - return _cryptoMethod->concatSign(data, sign); -} - -bool KeyStorage::check(const QByteArray &signedData, const QByteArray &publicKey) { - return _cryptoMethod->check(signedData, publicKey); -} - -void KeyStorage::setGenesisList(const QList& list) { - _keysMutex->lock(); - for (const auto& i : list) { - _keys.insert(i, {}); - } - _keysMutex->unlock(); - - start(); -} - -bool KeyStorage::toStorage(const QString &key) const { - - if (!isValid()) - return false; - - _keysMutex->lock(); - CryptoPairKeys value = _keys.value(key); - _keysMutex->unlock(); - - auto filePath = storageLocation() + "/" + key; - - QFile file(filePath); - - if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - return false; - } - - file.setPermissions(QFile::Permission::ReadOwner | QFile::Permission::WriteOwner); - - QDataStream stream(&file); - - stream << value; - - file.close(); - - return true; -} - -bool KeyStorage::fromStorage(const QByteArray &key) { - auto filePath = storageLocation() + "/" + key; - - QFile file(filePath); - - if (!file.open(QIODevice::ReadOnly)) { - return false; - } - - QDataStream stream(&file); - - CryptoPairKeys value; - stream >> value; - - file.close(); - - _keys.insert(key, value); - - return value.isValid(); -} - -void KeyStorage::generateKeysByTasks() { - _taskMutex->lock(); - auto tasks = _generateTasks; - _taskMutex->unlock(); - - for (auto it = tasks.begin(); it != tasks.end(); ++it) { - - if (_stopGenerator) { - return; - } - - const auto& value = _keys.value(it.key()); - if (!value.isValid()) { - - _keysMutex->lock(); - - if (it.value() == RAND_KEY && _randomKeysPool.size()) { - _keys[it.key()] = *_randomKeysPool.begin(); - _randomKeysPool.erase(_randomKeysPool.begin()); - } else { - _keys[it.key()] = _cryptoMethod->generate(it.value()); - } - - _keysMutex->unlock(); - - } - - _taskMutex->lock(); - _generateTasks.remove(it.key()); - _taskMutex->unlock(); - - } -} - -void KeyStorage::generateRandomKeys() { - _keyPoolSizeMutex->lock(); - int size = _keyPoolSize; - _keyPoolSizeMutex->unlock(); - - while (size > _randomKeysPool.size()) { - - if ((_stopGenerator)) - return; - - auto &&keys = _cryptoMethod->generate(); - - _keysMutex->lock(); - _randomKeysPool.insert(keys); - _keysMutex->unlock(); - } -} - -void KeyStorage::run() { - - if (_stopGenerator) { - return; - } - - _keyPoolSizeMutex->lock(); - int keyPoolSize = _keyPoolSize; - _keyPoolSizeMutex->unlock(); - - while ((_generateTasks.size() || keyPoolSize > _randomKeysPool.size()) - && !_stopGenerator) { - - generateKeysByTasks(); - generateRandomKeys(); - - _keyPoolSizeMutex->lock(); - keyPoolSize = _keyPoolSize; - _keyPoolSizeMutex->unlock(); - } -} - -void KeyStorage::stop() { - _stopGenerator = true; -} - -bool KeyStorage::waitForGeneratekey(const QString& key, int timeout) const { - return waitFor([this, &key](){return _keys.contains(key);}, timeout); -} - -bool KeyStorage::waitForThreadFinished(int timeout) const { - return waitFor([this](){return !isRunning();}, timeout); -} - -bool KeyStorage::waitFor(const std::function &checkFunc, int timeout) const { - auto waitFor = timeout + QDateTime::currentMSecsSinceEpoch(); - while (!checkFunc() && waitFor > QDateTime::currentMSecsSinceEpoch()) { - QCoreApplication::processEvents(); - } - - return checkFunc(); -} - -void KeyStorage::loadAllKeysFromStorage() { - auto list = QDir(storageLocation()).entryInfoList(QDir::Files | QDir::NoDotAndDotDot); - - for (const auto& file: list ) { - if (file.fileName() != VERSION_FILE) { - fromStorage(file.fileName().toLatin1()); - } - } -} - -bool KeyStorage::saveStorage() const { - - bool result = true; - for (auto it = _keys.begin(); it != _keys.end(); ++it) { - result = result && toStorage(it.key()); - } - - return result; -} - -bool KeyStorage::genKey(const QString &accessKey, const QByteArray &genesis) { - - if (accessKey.isEmpty()) - return false; - - QMutexLocker locker(_taskMutex); - _generateTasks.insert(accessKey, genesis); - return true; -} - -QString KeyStorage::storageLocation() const { - return _storageLocation; -} - -bool KeyStorage::initStorageLocation(const QString &value) { - QFile version(value + "/" + VERSION_FILE); - - if (!QFile::exists(value)) { - - if (!QDir().mkpath(value)) { - QuasarAppUtils::Params::log(" fail to create a key storagge. Into " - + value, QuasarAppUtils::Error); - return false; - } - - QFile::setPermissions(value, - QFile::Permission::ExeOwner | - QFile::Permission::ReadOwner | - QFile::Permission::WriteOwner); - - QFile version(value + "/" + VERSION_FILE); - - if (!version.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - return false; - } - - QDataStream stream(&version); - stream << THE_CLASS(_cryptoMethod); - version.close(); - - } else { - - if (!version.open(QIODevice::ReadOnly)) { - return false; - } - - QDataStream stream(&version); - QString versionName; - stream >> versionName; - version.close(); - - if (THE_CLASS(_cryptoMethod) != versionName) { - return false; - } - - } - - _storageLocation = value; - - return _storageLocation.size(); - -} - -bool KeyStorage::initDefaultStorageLocation(const QString &dirName) { - auto storageLoation = - QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + - "/" + dirName; - - if (dirName.isEmpty()) { - storageLoation += THE_CLASS(_cryptoMethod); - } - - storageLoation += "/crypto/"; - - if (!initStorageLocation(storageLoation)) { - QuasarAppUtils::Params::log("CryptoStorage not inited", - QuasarAppUtils::Error); - - return false; - } - - loadAllKeysFromStorage(); - - return _inited = true; -} - -void KeyStorage::clearStorage() const { - QDir::root().remove(storageLocation()); -} - -} diff --git a/Heart/AbstractSpace/keystorage.h b/Heart/AbstractSpace/keystorage.h deleted file mode 100644 index f0587e8..0000000 --- a/Heart/AbstractSpace/keystorage.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2018-2022 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 KEYSTORAGE_H -#define KEYSTORAGE_H - -#include -#include -#include "heart_global.h" -#include -#include -#include -#include "config.h" - -#define RAND_KEY "" - -class QMutex; - - -namespace QH { - -class CryptoPairKeys; -class ICrypto; -/** - * @brief The KeyStorage class provide the functionality of control crypto keys (generate, save and write). - * The current implementation of the key storage is collected cryptokeys like files in a key storage location. - * - * Work scheme: - *\image html KeyStorage.svg width=800px - */ -class HEARTSHARED_EXPORT KeyStorage: public QThread -{ - Q_OBJECT -public: - /** - * @brief KeyStorage - * @param cryptoMethod This is pointer to any class inherited from ICrypto - */ - KeyStorage(ICrypto* cryptoMethod); - ~KeyStorage(); - - /** - * @brief getNextPair This method take a one pair key from the keys pool or generate a new keys pair if the keys pool is empty. - * @warning If key pool is empty then this method frease a current thread for awaiting f neg generated pair key. - * @note if the key is not generated within the specified period of time, an invalid copy of the key pair will be returned. - * @param accsessKey The byte array for get a accesses to key from storage. - * @param genesis Set this params to empty for get random key pair or set the byte array for get a key pair for genesis array. - * @param timeout_msec This is timeout in milisecunds. default is WAIT_TIME (30000) - * @return pair of keys. - */ - CryptoPairKeys getNextPair(const QString &accsessKey, - const QByteArray &genesis = RAND_KEY, - int timeout_msec = WAIT_TIME); - - /** - * @brief getKeyPoolSize - This method return size of keyPool. - * By default it is 1. - * @return value of keys pool size. - */ - int getKeyPoolSize() const; - - /** - * @brief setKeyPoolSize This method return the size of keys pool. - * and start new work for generation a new keys. - * @param keyPoolSize This is a new size of pool. - */ - void setKeyPoolSize(int keyPoolSize); - - /** - * @brief isValid This method check keysStorage to valid. - * @return true if the crypto object is valid. - */ - virtual bool isValid() const; - - /** - * @brief isInited This method returns true if the crypto object was initialized correctly. - * @return true if the crypto object was initialized correctly. - */ - virtual bool isInited() const; - - /** - * @brief crypt This method crypted a data message using a publicKey. - * @param data This is pointer to data array for crypting. - * @note data has ben changed after call this method. - * @param publicKey This is key for crypting data. - * @return true if function finished successful. - */ - bool crypt(QByteArray *data, const QByteArray& publicKey); - - /** - * @brief decrypt This method decrypt a data message using a privateKey. - * @param cryptedData - Pointer to data array for decrypting. - * @note cryptedData Has been changed after call this method. - * @param privateKey This is private key for decrypting data. - * @return true if function finished successful. - */ - bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey); - - /** - * @brief sign This method sign a message using a privateKey. - * @param data This is pointer to data array for signed. - * @note data has been changed after call this method. - * @param privateKey This is key for signing a data message. - * @return true if function finished successful. - */ - bool sign(QByteArray* data, const QByteArray& privateKey); - - /** - * @brief extractSign This method extract sign from signed byteArray. - * @param data This is a signed message. - * @return return array of sign. - */ - QByteArray extractSign(const QByteArray& data); - - /** - * @brief concatSign This method concat a data of message and signs of a message. - * @param data This is message data. - * @param sign This is a sign of message. - * @return signed message. - */ - QByteArray concatSign(const QByteArray& data, const QByteArray& sign); - - /** - * @brief check This method fore validation signed message. - * @param signedData This is signed message for checking. - * @param publicKey This is public key for validation of message. - * @return true if function finished successful and signedData is valid. - */ - bool check(const QByteArray& signedData, const QByteArray& publicKey); - - /** - * @brief setGenesisList - set genesis list for generation key pairs. - * After invoke this method for each all items will be generated a keys pair. - */ - void setGenesisList(const QList &list); - - /** - * @brief storageLocation This method return a path of the storage location. - * By default storageLocation is QStandardPaths::DataLocation/KeysStorage - * @return path to storage location of crypto keys. - */ - QString storageLocation() const; - - /** - * @brief initStorageLocation This method set a new path for storage location of keys. - * @param value This is a new path to storage location. - */ - bool initStorageLocation(const QString &value); - - /** - * @brief initDefaultStorageLocation These is some as initStorageLocation, - * but set default path. - * @param dirName This is name of storage location. If This parametr weel be empty then - * storage location set default direction name. By default is name of crypto class. - * By default path of storage is: - * \code - * QStandardPaths::AppDataLocation/crypto/dirName; - * \endcode - * @return true if the storage inited successful. - */ - bool initDefaultStorageLocation(const QString& dirName = ""); - - /** - * @brief clearStorage - This method clear all storage. - */ - void clearStorage() const; - -protected: - - /** - * @brief toStorage This method save key into local storage. - * @param key This is key data value of keys pair. - * @note override this method if you want to change storage location or method of save of keys. - * @return true if key saved successful. - */ - virtual bool toStorage(const QString &key) const; - - /** - * @brief fromStorage This method load keys from local storage. - * @param key This is key data value of keys pair. - * @return true if key pair saved successful. - */ - virtual bool fromStorage(const QByteArray& key); - - /** - * @brief run This method start the key generator on own thread. - */ - void run() override; - - /** - * @brief stop This method stop generate keys. - */ - void stop(); -private: - - /** - * @brief waitForGeneratekey. - * @param timeout - maximum time for generation new key. by default = WAIT_TIME (30000) - * @return true if key generated successful. - */ - bool waitForGeneratekey(const QString &key, int timeout = WAIT_TIME) const; - - /** - * @brief waitForThreadFinished - * @param timeout - * @return - */ - bool waitForThreadFinished(int timeout = WAIT_TIME) const; - - /** - * @brief waitFor - Base wait function. - * @param checkFunc - This is lambda of check event. - * @param timeout - Maximum time line of waiting of event. - * @return true if event is checkFunc return true. - */ - bool waitFor(const std::function& checkFunc, int timeout) const; - - /** - * @brief loadAllKeysFromStorage - */ - void loadAllKeysFromStorage(); - - /** - * @brief saveStorage This method for saved keys in storage. - * @return true if all keys has been saved in a storage. - */ - bool saveStorage() const; - - /** - * @brief genKey - this method add a new task for generate keys pair - * @param accessKey - the byte array for get access of the keys pair. - * @param genesis - The byte array for generate new key. - * @note If access key well be empty then this method return false. - * @note For generate random key use a RAND_KEY genesis or empty value. - * @return true if task of generation a new pair keys added successful else false. - */ - bool genKey(const QString &accessKey, const QByteArray& genesis = RAND_KEY); - - QHash _keys; - QSet _randomKeysPool; - - QHash _generateTasks; - - int _keyPoolSize = 1; - - QMutex *_keyPoolSizeMutex = nullptr; - QMutex *_keysMutex = nullptr; - QMutex *_taskMutex = nullptr; - - QString _storageLocation; - - bool _inited = false; - bool _stopGenerator = false; - - ICrypto *_cryptoMethod = nullptr; - - void generateKeysByTasks(); - void generateRandomKeys(); -}; -} -#endif // KEYSTORAGE_H diff --git a/Heart/CMakeLists.txt b/Heart/CMakeLists.txt index e9cbf65..721775b 100644 --- a/Heart/CMakeLists.txt +++ b/Heart/CMakeLists.txt @@ -36,6 +36,7 @@ if (${HEART_BUILD_LVL} GREATER_EQUAL 0) "AbstractSpace/*.cpp" "AbstractSpace/*.h" "AbstractSpace/*.qrc" "AbstractSpace/packages/*.cpp" "AbstractSpace/packages/*.h" "AbstractSpace/packages/*.qrc" "AbstractSpace/Private/*.cpp" "AbstractSpace/Private/*.h" "AbstractSpace/Private/*.qrc" + "AbstractSpace/hcrypto/*.cpp" "AbstractSpace/hcrypto/*.h" "AbstractSpace/hcrypto/*.qrc" ) diff --git a/Heart/DataBaseSpace/databasenode.cpp b/Heart/DataBaseSpace/databasenode.cpp index e406d83..d668253 100644 --- a/Heart/DataBaseSpace/databasenode.cpp +++ b/Heart/DataBaseSpace/databasenode.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/Heart/DataBaseSpace/packages/abstractnetworkmember.cpp b/Heart/DataBaseSpace/packages/abstractnetworkmember.cpp index 50b18ae..e9cf5a7 100644 --- a/Heart/DataBaseSpace/packages/abstractnetworkmember.cpp +++ b/Heart/DataBaseSpace/packages/abstractnetworkmember.cpp @@ -16,7 +16,7 @@ namespace QH { namespace PKG { -AbstractNetworkMember::AbstractNetworkMember():DBObject("NetworkMembers") { +AbstractNetworkMember::AbstractNetworkMember(): { } @@ -32,6 +32,7 @@ AbstractNetworkMember::AbstractNetworkMember(const QString& id): bool AbstractNetworkMember::fromSqlRecord(const QSqlRecord &q) { + setId(q.value("id").toString()); setAuthenticationData(q.value("authenticationData").toByteArray()); setTrust(q.value("trust").toInt()); @@ -88,6 +89,10 @@ void AbstractNetworkMember::setId(const QString &newId) { _id = newId; } +QString AbstractNetworkMember::table() const { + return "NetworkMembers"; +} + int AbstractNetworkMember::trust() const { return _trust; } diff --git a/Heart/DataBaseSpace/packages/abstractnetworkmember.h b/Heart/DataBaseSpace/packages/abstractnetworkmember.h index ec3841e..811fe56 100644 --- a/Heart/DataBaseSpace/packages/abstractnetworkmember.h +++ b/Heart/DataBaseSpace/packages/abstractnetworkmember.h @@ -79,6 +79,7 @@ public: */ void setId(const QString &newId); + QString table() const override; protected: // StreamBase interface diff --git a/Heart/DataBaseSpace/packages/dbobject.cpp b/Heart/DataBaseSpace/packages/dbobject.cpp index 485b243..b1fab05 100644 --- a/Heart/DataBaseSpace/packages/dbobject.cpp +++ b/Heart/DataBaseSpace/packages/dbobject.cpp @@ -21,19 +21,14 @@ namespace QH { namespace PKG { -DBObject::DBObject(const QString &tableName) { +DBObject::DBObject() { DBObject::clear(); - _table = tableName; } DBObject::~DBObject() { } -QString DBObject::tableName() const { - return _table; -} - PrepareResult DBObject::prepareSelectQuery(QSqlQuery &q) const { auto map = variantMap().keys(); @@ -244,7 +239,7 @@ bool DBObject::isInsertPrimaryKey() const { } DbAddress DBObject::dbAddress() const { - return {_table, primaryValue()}; + return {table(), primaryValue()}; } DBObject *DBObject::cloneRaw() const { diff --git a/Heart/DataBaseSpace/packages/dbobject.h b/Heart/DataBaseSpace/packages/dbobject.h index 90c4c31..af9ebaa 100644 --- a/Heart/DataBaseSpace/packages/dbobject.h +++ b/Heart/DataBaseSpace/packages/dbobject.h @@ -102,11 +102,7 @@ class HEARTSHARED_EXPORT DBObject : public AbstractData, public ISubscribableDat public: - /** - * @brief DBObject This is default constructor.Before using this class you need set the table name and primary key of this object. - * @param tableName This is table name. - */ - DBObject(const QString& tableName); + DBObject(); ~DBObject() override; @@ -135,12 +131,6 @@ public: */ virtual void clear(); - /** - * @brief tableName This method return a table name of the database object. - * @return string value if the table name. - */ - QString tableName() const; - /** * @brief createDBObject This method should be create a object with the some type as the object called this method. * Example of override: @@ -213,7 +203,7 @@ public: QString queryString = "INSERT INTO %0(%1) VALUES (%2) "; - queryString = queryString.arg(tableName()); + queryString = queryString.arg(table()); QString tableInsertHeader = ""; QString tableInsertValues = ""; @@ -267,7 +257,7 @@ public: QString queryString = "UPDATE %0 SET %1 WHERE %2"; - queryString = queryString.arg(tableName()); + queryString = queryString.arg(table()); QString tableUpdateValues = ""; QString tableUpdateRules = QString("%0 = :%0"). arg(primaryKey()); @@ -465,6 +455,12 @@ protected: */ virtual QString primaryValue() const = 0; + /** + * @brief table This method should be return name of the database table that should be contains objects with this type. + * @return table name that contains object with this type. + */ + virtual QString table() const = 0; + /** * @brief isInsertPrimaryKey This method check primaryKeys type. * If the primary key have a type MemberType::Insert then return true. @@ -475,7 +471,6 @@ protected: private: QString getWhereBlock() const; bool _printError = true; - QString _table; }; } } diff --git a/Heart/DataBaseSpace/singleclient.cpp b/Heart/DataBaseSpace/singleclient.cpp index dc4ad46..8675152 100644 --- a/Heart/DataBaseSpace/singleclient.cpp +++ b/Heart/DataBaseSpace/singleclient.cpp @@ -155,7 +155,8 @@ bool SingleClient::removeUser() { QH::PKG::DeleteObject request; - request.copyFrom(&getMember()); + request.setAddress(getMember().dbAddress()); + if (!sendData(&request, realServerAddress())) { return false; }; diff --git a/Heart/DataBaseSpace/sqldbwriter.cpp b/Heart/DataBaseSpace/sqldbwriter.cpp index 42dd7f1..e06e0f3 100644 --- a/Heart/DataBaseSpace/sqldbwriter.cpp +++ b/Heart/DataBaseSpace/sqldbwriter.cpp @@ -391,7 +391,9 @@ bool SqlDBWriter::selectQuery(const DBObject& requestObject, while (q.next()) { if (!newObject->fromSqlRecord(q.record())) { - QuasarAppUtils::Params::log("Init sql object error.", + QuasarAppUtils::Params::log("Select query finished successful but, " + "the fromSqlRecord method return false." + + newObject->toString(), QuasarAppUtils::Error); return false; } diff --git a/HeartTests/AbstractSpace/abstractnodetest.cpp b/HeartTests/AbstractSpace/abstractnodetest.cpp index 14b4c2a..32f84e3 100644 --- a/HeartTests/AbstractSpace/abstractnodetest.cpp +++ b/HeartTests/AbstractSpace/abstractnodetest.cpp @@ -10,7 +10,6 @@ #include "testutils.h" #include -#include #include #define LOCAL_TEST_PORT TEST_PORT + 1 diff --git a/HeartTests/DataBaseSpace/basenodetest.cpp b/HeartTests/DataBaseSpace/basenodetest.cpp index b3e8ae0..ae741f0 100644 --- a/HeartTests/DataBaseSpace/basenodetest.cpp +++ b/HeartTests/DataBaseSpace/basenodetest.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #define LOCAL_TEST_PORT TEST_PORT + 2 diff --git a/HeartTests/DataBaseSpace/templatedatabasenodeunittests.h b/HeartTests/DataBaseSpace/templatedatabasenodeunittests.h index e13f077..1402172 100644 --- a/HeartTests/DataBaseSpace/templatedatabasenodeunittests.h +++ b/HeartTests/DataBaseSpace/templatedatabasenodeunittests.h @@ -96,7 +96,7 @@ protected: // create request for get all objects from database. QH::PKG::DBObjectsRequest setRequest( - testObjec->tableName(), ""); + testObjec->table(), ""); auto list = BASE::db()->getObject(setRequest); QVERIFY(list);