From c472d04c875ea06c2991a21ea0d4b10ac276d96f Mon Sep 17 00:00:00 2001 From: EndrII Date: Tue, 4 Jul 2023 17:12:16 +0200 Subject: [PATCH] added rsa implementation for openssl 1.1 --- src/lib/src/private/easysslutils.cpp | 44 ++++++++++ src/lib/src/private/easysslutils.h | 44 ++++++++++ src/lib/src/public/easyssl/ecdsassl11.cpp | 59 ++++--------- src/lib/src/public/easyssl/rsassl11.cpp | 100 ++++++++++++++++++++++ 4 files changed, 203 insertions(+), 44 deletions(-) create mode 100644 src/lib/src/private/easysslutils.cpp create mode 100644 src/lib/src/private/easysslutils.h diff --git a/src/lib/src/private/easysslutils.cpp b/src/lib/src/private/easysslutils.cpp new file mode 100644 index 0000000..0c9ea28 --- /dev/null +++ b/src/lib/src/private/easysslutils.cpp @@ -0,0 +1,44 @@ +//# +//# 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 "easysslutils.h" +#include +#include +#include +#include + +namespace EasySSL { + + +void EasySSLUtils::printlastOpenSSlError() { + int error = ERR_get_error(); + char buffer[256]; + ERR_error_string(error, buffer); +} + +QByteArray EasySSLUtils::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 *EasySSLUtils::bignumFromArray(const QByteArray &array) { + auto d = reinterpret_cast(array.data()); + BIGNUM* result = BN_mpi2bn(d, + array.length(), nullptr); + if (!result) { + printlastOpenSSlError(); + } + + return result; +} + + +} diff --git a/src/lib/src/private/easysslutils.h b/src/lib/src/private/easysslutils.h new file mode 100644 index 0000000..030b249 --- /dev/null +++ b/src/lib/src/private/easysslutils.h @@ -0,0 +1,44 @@ +//# +//# 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 + +#include +namespace EasySSL { + +/** + * @brief The EasySSLUtils class This is base utils for work with opwnssl library. + */ +class EasySSLUtils { + +public: + + /** + * @brief printlastOpenSSlError This method print last ssl error message. + */ + static void printlastOpenSSlError(); + + /** + * @brief bignumToArray This method convert openssl BIGNUM into byteArray + * @param num This is big num of the openssl library + * @return bytes array. + */ + static QByteArray bignumToArray(const BIGNUM* num); + + /** + * @brief bignumFromArray This method convert Qt bytes array into opensll big num. + * @param array This is input array. + * @return big num pointer. + * @note This result pointer will not free automatically. Please free returned pointer after using. + */ + [[nodiscard("This pointer will not free automatically. Please free returned pointer after using.")]] + static BIGNUM* bignumFromArray(const QByteArray& array); +}; + + + +}; diff --git a/src/lib/src/public/easyssl/ecdsassl11.cpp b/src/lib/src/public/easyssl/ecdsassl11.cpp index 99948dd..e36688d 100644 --- a/src/lib/src/public/easyssl/ecdsassl11.cpp +++ b/src/lib/src/public/easyssl/ecdsassl11.cpp @@ -17,15 +17,10 @@ #include #include #include +#include namespace EasySSL { -void printlastOpenSSlError() { - int error = ERR_get_error(); - char buffer[256]; - ERR_error_string(error, buffer); -} - bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) { // input data should be valid pointers to pointers of key and group objects. @@ -46,7 +41,7 @@ bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) { *eckey = EC_KEY_new(); if (!*eckey) { - printlastOpenSSlError(); + EasySSLUtils::printlastOpenSSlError(); free(); return false; } @@ -54,13 +49,13 @@ bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) { *ecgroup = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!*ecgroup) { - printlastOpenSSlError(); + EasySSLUtils::printlastOpenSSlError(); free(); return false; } if (!EC_KEY_set_group(*eckey, *ecgroup)) { - printlastOpenSSlError(); + EasySSLUtils::printlastOpenSSlError(); free(); return false; } @@ -69,33 +64,11 @@ bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) { } -ECDSASSL11::ECDSASSL11() { - -} - -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; -} +ECDSASSL11::ECDSASSL11() {} QByteArray extractPrivateKey(EC_KEY* ec_key) { const BIGNUM* ec_priv = EC_KEY_get0_private_key(ec_key); - return bignumToArray(ec_priv); + return EasySSLUtils::bignumToArray(ec_priv); } QByteArray extractPublicKey(EC_KEY* key, EC_GROUP* group) { @@ -107,7 +80,7 @@ QByteArray extractPublicKey(EC_KEY* key, EC_GROUP* group) { size_t length = EC_KEY_key2buf(key, form, &pub_key_buffer, nullptr); if (length <= 0) { - printlastOpenSSlError(); + EasySSLUtils::printlastOpenSSlError(); return {}; } @@ -128,7 +101,7 @@ bool ECDSASSL11::makeKeys(QByteArray &pubKey, QByteArray &privKey) const { } if (!EC_KEY_generate_key(eckey)) { - printlastOpenSSlError(); + EasySSLUtils::printlastOpenSSlError(); EC_GROUP_free(ecgroup); EC_KEY_free(eckey); return false; @@ -157,9 +130,9 @@ QByteArray ECDSASSL11::signMessage(const QByteArray &inputData, auto hash = QCryptographicHash::hash(inputData, QCryptographicHash::Sha256); - BIGNUM* priv = bignumFromArray(key); + BIGNUM* priv = EasySSLUtils::bignumFromArray(key); if (!EC_KEY_set_private_key(eckey, priv)) { - printlastOpenSSlError(); + EasySSLUtils::printlastOpenSSlError(); EC_GROUP_free(ecgroup); EC_KEY_free(eckey); return {}; @@ -172,7 +145,7 @@ QByteArray ECDSASSL11::signMessage(const QByteArray &inputData, EC_GROUP_free(ecgroup); if (!signature) { - printlastOpenSSlError(); + EasySSLUtils::printlastOpenSSlError(); return {}; } @@ -182,8 +155,8 @@ QByteArray ECDSASSL11::signMessage(const QByteArray &inputData, QByteArray result; QDataStream stream(&result, QIODevice::WriteOnly); - stream << bignumToArray(R); - stream << bignumToArray(S); + stream << EasySSLUtils::bignumToArray(R); + stream << EasySSLUtils::bignumToArray(S); ECDSA_SIG_free(signature); @@ -203,8 +176,8 @@ bool ECDSASSL11::checkSign(const QByteArray &inputData, QByteArray rR,rS; stream >> rR; stream >> rS; - R = bignumFromArray(rR); - S = bignumFromArray(rS); + R = EasySSLUtils::bignumFromArray(rR); + S = EasySSLUtils::bignumFromArray(rS); ECDSA_SIG *sig = ECDSA_SIG_new(); ECDSA_SIG_set0(sig, R, S); @@ -212,7 +185,6 @@ bool ECDSASSL11::checkSign(const QByteArray &inputData, auto hash = QCryptographicHash::hash(inputData, QCryptographicHash::Sha256); - EC_KEY *eckey= nullptr; EC_GROUP *ecgroup = nullptr; @@ -221,7 +193,6 @@ bool ECDSASSL11::checkSign(const QByteArray &inputData, return {}; } - // extract key from raw array; EC_POINT* ec_point = EC_POINT_new(ecgroup); EC_POINT_oct2point(ecgroup, ec_point, diff --git a/src/lib/src/public/easyssl/rsassl11.cpp b/src/lib/src/public/easyssl/rsassl11.cpp index 71d1876..da3b05e 100644 --- a/src/lib/src/public/easyssl/rsassl11.cpp +++ b/src/lib/src/public/easyssl/rsassl11.cpp @@ -7,6 +7,7 @@ #include "rsassl11.h" +#include "qcryptographichash.h" #include #include #include @@ -81,19 +82,118 @@ ICrypto::Features RSASSL11::supportedFeatures() const { } QByteArray RSASSL11::signMessage(const QByteArray &inputData, const QByteArray &key) const { + QByteArray signature; + BIO* privateKeyBio = BIO_new_mem_buf(key.data(), key.size()); + + RSA* rsaPrivateKey = PEM_read_bio_RSAPrivateKey(privateKeyBio, nullptr, nullptr, nullptr); + BIO_free(privateKeyBio); + + if (!rsaPrivateKey) { + perror("Error reading private key"); + return {}; + } + + auto hash = QCryptographicHash::hash(inputData, + QCryptographicHash::Sha256); + + signature.resize(RSA_size(rsaPrivateKey)); + unsigned int signatureLength = 0; + int result = RSA_sign(NID_sha256, reinterpret_cast(hash.data()), + hash.size(), reinterpret_cast(signature.data()), + &signatureLength, rsaPrivateKey); + RSA_free(rsaPrivateKey); + + if (result != 1) { + perror("Error signing message"); + return {}; + } + + signature.resize(signatureLength); + return signature; } bool RSASSL11::checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const { + BIO* publicKeyBio = BIO_new_mem_buf(key.data(), key.size()); + RSA* rsaPublicKey = PEM_read_bio_RSA_PUBKEY(publicKeyBio, nullptr, nullptr, nullptr); + BIO_free(publicKeyBio); + + if (!rsaPublicKey) { + perror("Error reading public key"); + return false; + } + + auto hash = QCryptographicHash::hash(inputData, + QCryptographicHash::Sha256); + + int result = RSA_verify(NID_sha256, reinterpret_cast(hash.data()), + hash.size(), reinterpret_cast(signature.data()), + signature.size(), rsaPublicKey); + RSA_free(rsaPublicKey); + + if (result != 1) { + perror("Error verifying signature"); + return false; + } + + return true; } QByteArray RSASSL11::decrypt(const QByteArray &message, const QByteArray &key) { + QByteArray decryptedMessage; + BIO* privateKeyBio = BIO_new_mem_buf(key.data(), key.size()); + + RSA* rsaPrivateKey = PEM_read_bio_RSAPrivateKey(privateKeyBio, nullptr, nullptr, nullptr); + BIO_free(privateKeyBio); + + if (!rsaPrivateKey) { + perror("Error reading private key"); + return {}; + } + + decryptedMessage.resize(RSA_size(rsaPrivateKey)); + int result = RSA_private_decrypt(message.size(), + reinterpret_cast(message.data()), + reinterpret_cast(decryptedMessage.data()), + rsaPrivateKey, RSA_PKCS1_PADDING); + RSA_free(rsaPrivateKey); + + if (result == -1) { + perror("Error decrypting ciphertext"); + return {}; + } + + return decryptedMessage; } QByteArray RSASSL11::encrypt(const QByteArray &message, const QByteArray &key) { + QByteArray encryptedMessage; + BIO* publicKeyBio = BIO_new_mem_buf(key.data(), key.size()); + RSA* rsaPublicKey = PEM_read_bio_RSA_PUBKEY(publicKeyBio, nullptr, nullptr, nullptr); + BIO_free(publicKeyBio); + + if (!rsaPublicKey) { + perror("Error reading public key"); + return {}; + } + + encryptedMessage.resize(RSA_size(rsaPublicKey)); + + int result = RSA_public_encrypt(message.size(), + reinterpret_cast(message.data()), + reinterpret_cast(encryptedMessage.data()), + rsaPublicKey, RSA_PKCS1_PADDING); + RSA_free(rsaPublicKey); + + if (result == -1) { + perror("Error encrypting message"); + return {}; + } + + return encryptedMessage; } }