mirror of
https://github.com/QuasarApp/Heart.git
synced 2025-04-26 09:44:37 +00:00
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
This commit is contained in:
parent
541e552d00
commit
bc48851164
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
@ -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)
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include "abstractnodetest.h"
|
||||
#include <shedullertest.h>
|
||||
#include <bigdatatest.h>
|
||||
#include <ecdsaauthtest.h>
|
||||
#include <upgradedatabasetest.h>
|
||||
#include <multiversiontest.h>
|
||||
|
||||
@ -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)
|
||||
|
||||
|
@ -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 <QtTest>
|
||||
#include <hcryptoFeatures/authecdsa.h>
|
||||
#include <thread>
|
||||
|
||||
#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
|
@ -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
|
@ -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})
|
||||
|
@ -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); }
|
||||
|
||||
|
@ -17,12 +17,9 @@
|
||||
|
||||
#ifdef USE_HEART_SSL
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <sslsocket.h>
|
||||
#include <easyssl/x509.h>
|
||||
#include <easyssl/rsassl.h>
|
||||
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslCertificate>
|
||||
@ -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<unsigned char *>(data.country.toLatin1().data());
|
||||
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, C, -1, -1, 0);
|
||||
|
||||
unsigned char *O = reinterpret_cast<unsigned char *>(data.organization.toLatin1().data());
|
||||
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, O, -1, -1, 0);
|
||||
|
||||
unsigned char *CN = reinterpret_cast<unsigned char *>(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<int>(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<int>(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<EasySSL::RSASSL>::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<QSslError> &newIgnoreSslErrors
|
||||
_ignoreSslErrors = newIgnoreSslErrors;
|
||||
};
|
||||
|
||||
bool AbstractNode::useSelfSignedSslConfiguration(const SslSrtData &crtData) {
|
||||
bool AbstractNode::useSelfSignedSslConfiguration(const EasySSL::SslSrtData &crtData) {
|
||||
|
||||
if (isListening()) {
|
||||
return false;
|
||||
|
@ -13,8 +13,8 @@
|
||||
#include "ping.h"
|
||||
|
||||
#ifdef USE_HEART_SSL
|
||||
#include <openssl/evp.h>
|
||||
#include <QSslConfiguration>
|
||||
#include <easyssl/icertificate.h>
|
||||
#endif
|
||||
|
||||
#include <QAbstractSocket>
|
||||
@ -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<QSslError> &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.
|
||||
|
@ -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 <openssl/ecdsa.h> // for ECDSA_do_sign, ECDSA_do_verify
|
||||
#include <openssl/obj_mac.h> // for NID_secp192k1
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDataStream>
|
||||
#include <QIODevice>
|
||||
#include <QVector>
|
||||
#include <quasarapp.h>
|
||||
|
||||
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<unsigned char> data(length);
|
||||
BN_bn2mpi(num, data.data());
|
||||
QByteArray result;
|
||||
result.insert(0, reinterpret_cast<char*>(data.data()), data.length());
|
||||
return result;
|
||||
}
|
||||
|
||||
BIGNUM* bignumFromArray(const QByteArray& array) {
|
||||
auto d = reinterpret_cast<const unsigned char*>(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<const char*>(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<const unsigned char*>(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<const unsigned char*>(key.data()),
|
||||
key.length(), nullptr);
|
||||
|
||||
EC_KEY_set_public_key(eckey, ec_point);
|
||||
|
||||
|
||||
int verify_status = ECDSA_do_verify(reinterpret_cast<const unsigned char*>(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
|
@ -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 <openssl/ec.h> // 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
|
@ -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 {
|
||||
|
||||
}
|
@ -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 <QByteArray>
|
||||
|
||||
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
|
@ -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 <QCryptographicHash>
|
||||
#include <time.h>
|
||||
#include <QString>
|
||||
|
||||
|
||||
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 <hcrypto.h>
|
||||
*
|
||||
* using ECDSAAuth = AsyncKeysAuth<ECDSA>;
|
||||
*
|
||||
* @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 CryptoImplementation>
|
||||
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<const char*>(&_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<const char*>(&_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
|
@ -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<ECDSASSL11> AuthECDSA;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AUTHECDSA_H
|
@ -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<ECDSASSL11> ECDSASigner;
|
||||
|
||||
}
|
||||
#endif // ECDSASIGNER_H
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 <streambase.h>
|
||||
|
||||
|
||||
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
|
@ -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 <QByteArray>
|
||||
#include <QCryptographicHash>
|
||||
#include <QSharedPointer>
|
||||
#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 <hcriptoFeatures/isignerdelegate.h>
|
||||
* #include <hcriptoFeatures/ecdsasigner.h>
|
||||
*
|
||||
* 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 CryptoImplementation>
|
||||
class Signer: protected QuasarAppUtils::Service<Signer<CryptoImplementation>>,
|
||||
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<CryptoImplementation>::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<CryptoImplementation>::autoInstance()) {
|
||||
return signer->checkSign(obj->getMessage(), obj->signature(), obj->getPublicKey());
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
#endif // SIGNER_H
|
@ -1 +1 @@
|
||||
Subproject commit 62c9d4e7c228647d67d77848ef90fe47e5039c22
|
||||
Subproject commit 53a67709ff90b544036cb90edbfe8cb1ded6dc0b
|
1
submodules/easyssl
Submodule
1
submodules/easyssl
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 83cea813075c1837c0dafc3036596c9667a5d213
|
Loading…
x
Reference in New Issue
Block a user