drop support not EVP interfaces

This commit is contained in:
Andrei Yankovich 2023-07-13 23:41:51 +02:00
parent a84929b069
commit 1ab0cc87bf
13 changed files with 250 additions and 525 deletions

View File

@ -16,9 +16,7 @@ namespace EasySSL {
void EasySSLUtils::printlastOpenSSlError() {
int error = ERR_get_error();
char buffer[256];
ERR_error_string(error, buffer);
ERR_print_errors_fp(stderr);
}
QByteArray EasySSLUtils::bignumToArray(const BIGNUM *num) {

View File

@ -9,7 +9,7 @@
#ifndef AUTHECDSA_H
#define AUTHECDSA_H
#include "ecdsassl11.h"
#include "ecdsassl.h"
#include "asynckeysauth.h"
namespace EasySSL {
@ -17,7 +17,7 @@ namespace EasySSL {
/**
* @brief The AuthECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library.
*/
typedef AsyncKeysAuth<ECDSASSL11> AuthECDSA;
typedef AsyncKeysAuth<ECDSASSL> AuthECDSA;
}

View File

@ -0,0 +1,154 @@
//#
//# 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 "ecdsassl.h"
#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 <easysslutils.h>
#include <QDebug>
#include <openssl/pem.h>
namespace EasySSL {
ECDSASSL::ECDSASSL() {}
EVP_PKEY * ECDSASSL::makeRawKeys() const {
EVP_PKEY *pkey = nullptr;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr);
if (!pctx) {
qCritical() << "Error reading public key";
return nullptr;
}
EVP_PKEY_keygen_init(pctx);
EVP_PKEY_generate(pctx, &pkey);
EVP_PKEY_CTX_free(pctx);
return pkey;
}
ICrypto::Features ECDSASSL::supportedFeatures() const {
return Features::Signing;
}
QSsl::KeyAlgorithm ECDSASSL::keyAlgorithm() const {
return QSsl::KeyAlgorithm::Ec;
}
QByteArray ECDSASSL::signMessage(const QByteArray &inputData,
const QByteArray &key) const {
QByteArray signature;
auto pkey = EasySSLUtils::byteArrayToBio(key);
auto ecPrivateKey = PEM_read_bio_PrivateKey(pkey, nullptr, nullptr, nullptr);
BIO_free(pkey);
if (!ecPrivateKey) {
qCritical() << "Error reading private key";
return {};
}
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
if (mdctx == nullptr) {
return {};
}
// Initialize the signing operation
if (EVP_DigestSignInit(mdctx, nullptr, EVP_sha256(), nullptr, ecPrivateKey) != 1) {
EVP_MD_CTX_free(mdctx);
return {};
}
auto hash = QCryptographicHash::hash(inputData,
QCryptographicHash::Sha256);
// Provide the message to be signed
if (EVP_DigestSignUpdate(mdctx, hash.data(), hash.size()) != 1) {
EVP_MD_CTX_free(mdctx);
return {};
}
size_t signatureLength = 0;
// Determine the length of the signature
if (EVP_DigestSignFinal(mdctx, nullptr, &signatureLength) != 1) {
EVP_MD_CTX_free(mdctx);
return {};
}
signature.resize(signatureLength);
// Perform the final signing operation and obtain the signature
if (EVP_DigestSignFinal(mdctx, reinterpret_cast<unsigned char*>(signature.data()), &signatureLength) != 1) {
EVP_MD_CTX_free(mdctx);
return {};
}
EVP_MD_CTX_free(mdctx);
return signature;
}
bool ECDSASSL::checkSign(const QByteArray &inputData,
const QByteArray &signature,
const QByteArray &key) const {
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
if (mdctx == nullptr) {
return false;
}
auto pkey = EasySSLUtils::byteArrayToBio(key);
auto rsaPublickKey = PEM_read_bio_PUBKEY(pkey, nullptr, nullptr, nullptr);
BIO_free(pkey);
// Initialize the verification operation
if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, rsaPublickKey) != 1) {
EVP_MD_CTX_free(mdctx);
return false;
}
auto hash = QCryptographicHash::hash(inputData,
QCryptographicHash::Sha256);
// Provide the message to be verified
if (EVP_DigestVerifyUpdate(mdctx, hash.data(), hash.size()) != 1) {
EVP_MD_CTX_free(mdctx);
return false;
}
// Perform the signature verification
int verificationResult = EVP_DigestVerifyFinal(mdctx,
reinterpret_cast<const unsigned char*>(signature.data()),
signature.length());
EVP_MD_CTX_free(mdctx);
return verificationResult == 1;
}
QByteArray ECDSASSL::decrypt(const QByteArray &, const QByteArray &) {
return {};
}
QByteArray ECDSASSL::encrypt(const QByteArray &, const QByteArray &) {
return {};
}
}

View File

@ -16,16 +16,15 @@ namespace EasySSL {
/**
* @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
*/
class EASYSSL_EXPORT ECDSASSL11: public EasySSL::ICrypto
class EASYSSL_EXPORT ECDSASSL: public EasySSL::ICrypto
{
public:
ECDSASSL11();
bool makeKeys(QByteArray &pubKey, QByteArray &privKey) const override;
ECDSASSL();
EVP_PKEY * makeRawKeys() const override;
Features supportedFeatures() const override;
QSsl::KeyAlgorithm keyAlgorithm() const override;
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override;
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override;
@ -42,7 +41,7 @@ public:
*/
QByteArray encrypt(const QByteArray &message, const QByteArray &key) override;
};
};
}

View File

@ -1,223 +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"
#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 <easysslutils.h>
namespace EasySSL {
bool 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) {
EasySSLUtils::printlastOpenSSlError();
free();
return false;
}
*ecgroup = EC_GROUP_new_by_curve_name(NID_secp256k1);
if (!*ecgroup) {
EasySSLUtils::printlastOpenSSlError();
free();
return false;
}
if (!EC_KEY_set_group(*eckey, *ecgroup)) {
EasySSLUtils::printlastOpenSSlError();
free();
return false;
}
return true;
}
ECDSASSL11::ECDSASSL11() {}
QByteArray extractPrivateKey(EC_KEY* ec_key) {
const BIGNUM* ec_priv = EC_KEY_get0_private_key(ec_key);
return EasySSLUtils::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) {
EasySSLUtils::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) const {
EC_KEY *eckey= nullptr;
EC_GROUP *ecgroup = nullptr;
if (!prepareKeyAdnGroupObjects(&eckey, &ecgroup)) {
return false;
}
if (!EC_KEY_generate_key(eckey)) {
EasySSLUtils::printlastOpenSSlError();
EC_GROUP_free(ecgroup);
EC_KEY_free(eckey);
return false;
}
pubKey = extractPublicKey(eckey, ecgroup);
privKey = extractPrivateKey(eckey);
return pubKey.length() && privKey.length();
}
ICrypto::Features ECDSASSL11::supportedFeatures() const {
return Features::Signing;
}
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 = EasySSLUtils::bignumFromArray(key);
if (!EC_KEY_set_private_key(eckey, priv)) {
EasySSLUtils::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) {
EasySSLUtils::printlastOpenSSlError();
return {};
}
const BIGNUM * R, *S;
ECDSA_SIG_get0(signature, &R, &S);
QByteArray result;
QDataStream stream(&result, QIODevice::WriteOnly);
stream << EasySSLUtils::bignumToArray(R);
stream << EasySSLUtils::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 = EasySSLUtils::bignumFromArray(rR);
S = EasySSLUtils::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::decrypt(const QByteArray &, const QByteArray &) {
return {};
}
QByteArray ECDSASSL11::encrypt(const QByteArray &, const QByteArray &) {
return {};
}
}

View File

@ -6,21 +6,22 @@
//#
#include "rsassl30.h"
#include "rsassl.h"
#include "qcryptographichash.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <easysslutils.h>
#include <QDebug>
namespace EasySSL {
RSASSL30::RSASSL30() {
RSASSL::RSASSL() {
}
EVP_PKEY * RSASSL30::makeRawKeys() const {
EVP_PKEY * RSASSL::makeRawKeys() const {
EVP_PKEY *pkey = nullptr;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(nullptr, "RSA", nullptr);
@ -33,11 +34,15 @@ EVP_PKEY * RSASSL30::makeRawKeys() const {
return pkey;
}
ICrypto::Features RSASSL30::supportedFeatures() const {
ICrypto::Features RSASSL::supportedFeatures() const {
return static_cast<ICrypto::Features>(Features::Encription | Features::Signing);
}
QByteArray RSASSL30::signMessage(const QByteArray &inputData, const QByteArray &key) const {
QSsl::KeyAlgorithm RSASSL::keyAlgorithm() const {
return QSsl::KeyAlgorithm::Rsa;
}
QByteArray RSASSL::signMessage(const QByteArray &inputData, const QByteArray &key) const {
QByteArray signature;
auto pkey = EasySSLUtils::byteArrayToBio(key);
@ -45,7 +50,7 @@ QByteArray RSASSL30::signMessage(const QByteArray &inputData, const QByteArray &
BIO_free(pkey);
if (!rsaPrivateKey) {
perror("Error reading private key");
qCritical() << "Error reading private key";
return {};
}
@ -88,7 +93,7 @@ QByteArray RSASSL30::signMessage(const QByteArray &inputData, const QByteArray &
return signature;
}
bool RSASSL30::checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const {
bool RSASSL::checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const {
EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
if (mdctx == nullptr) {
return false;
@ -123,17 +128,26 @@ bool RSASSL30::checkSign(const QByteArray &inputData, const QByteArray &signatur
return verificationResult == 1;
}
QByteArray RSASSL30::decrypt(const QByteArray &message, const QByteArray &key) {
QByteArray RSASSL::decrypt(const QByteArray &message, const QByteArray &key) {
auto pkey = EasySSLUtils::byteArrayToBio(key);
auto rsaPrivateKey = PEM_read_bio_PrivateKey(pkey, nullptr, nullptr, nullptr);
BIO_free(pkey);
if (!rsaPrivateKey) {
perror("Error reading private key");
qCritical() << "Error reading private key";
return {};
}
const long long maxDencryptedSize = EVP_PKEY_size(rsaPrivateKey);
if (message.length() % maxDencryptedSize) {
qCritical() << "Error wrong encripted data size.";
qCritical() << "Your key requir size multiple " << maxDencryptedSize;
return {};
}
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(rsaPrivateKey, nullptr);
if (ctx == nullptr) {
EVP_PKEY_free(rsaPrivateKey);
@ -152,18 +166,25 @@ QByteArray RSASSL30::decrypt(const QByteArray &message, const QByteArray &key) {
return {};
}
size_t decryptedDataLength = 0;
if (EVP_PKEY_decrypt(ctx, nullptr, &decryptedDataLength, reinterpret_cast<const unsigned char*>(message.constData()), message.length()) <= 0) {
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(rsaPrivateKey);
return {};
}
QByteArray decryptedData;
QByteArray decryptedData(decryptedDataLength, 0);
if (EVP_PKEY_decrypt(ctx, reinterpret_cast<unsigned char*>(decryptedData.data()), &decryptedDataLength, reinterpret_cast<const unsigned char*>(message.constData()), message.length()) <= 0) {
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(rsaPrivateKey);
return {};
for (int index = 0; index < message.size(); index += maxDencryptedSize) {
QByteArray decryptedDataPart(maxDencryptedSize, 0);
size_t realDecryptedDataPartSize = 0;
if (EVP_PKEY_decrypt(ctx,
reinterpret_cast<unsigned char*>(decryptedDataPart.data()),
&realDecryptedDataPartSize,
reinterpret_cast<const unsigned char*>(&(message.constData()[index])),
maxDencryptedSize) <= 0) {
EasySSLUtils::printlastOpenSSlError();
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(rsaPrivateKey);
return {};
}
decryptedData += decryptedDataPart.left(realDecryptedDataPartSize);
}
EVP_PKEY_CTX_free(ctx);
@ -172,13 +193,13 @@ QByteArray RSASSL30::decrypt(const QByteArray &message, const QByteArray &key) {
}
QByteArray RSASSL30::encrypt(const QByteArray &message, const QByteArray &key) {
QByteArray RSASSL::encrypt(const QByteArray &message, const QByteArray &key) {
auto pkey = EasySSLUtils::byteArrayToBio(key);
auto rsaPublicKey = PEM_read_bio_PUBKEY(pkey, nullptr, nullptr, nullptr);
BIO_free(pkey);
if (!rsaPublicKey) {
perror("Error reading public key");
qCritical() << "Error reading public key";
return {};
}
@ -200,18 +221,27 @@ QByteArray RSASSL30::encrypt(const QByteArray &message, const QByteArray &key) {
return {};
}
size_t encryptedDataLength = 0;
if (EVP_PKEY_encrypt(ctx, nullptr, &encryptedDataLength, reinterpret_cast<const unsigned char*>(message.constData()), message.length()) <= 0) {
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(rsaPublicKey);
return {};
}
const long long maxEncryptedSize = EVP_PKEY_size(rsaPublicKey);
QByteArray encryptedData;
QByteArray encryptedData(encryptedDataLength, 0);
if (EVP_PKEY_encrypt(ctx, reinterpret_cast<unsigned char*>(encryptedData.data()), &encryptedDataLength, reinterpret_cast<const unsigned char*>(message.constData()), message.length()) <= 0) {
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(rsaPublicKey);
return {};
for (int index = 0; index < message.size();) {
QByteArray encryptedDataPart(maxEncryptedSize, 0);
size_t realEncryptedDataPartSize = 0;
int currentPartSize = std::min(message.length() - index, maxEncryptedSize);
if (EVP_PKEY_encrypt(ctx,
reinterpret_cast<unsigned char*>(encryptedDataPart.data()),
&realEncryptedDataPartSize,
reinterpret_cast<const unsigned char*>(&(message.constData()[index])),
currentPartSize) <= 0) {
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(rsaPublicKey);
return {};
}
encryptedData += encryptedDataPart.left(realEncryptedDataPartSize);
index += currentPartSize;
}
EVP_PKEY_CTX_free(ctx);

View File

@ -17,13 +17,14 @@ namespace EasySSL {
/**
* @brief The RSASSL30 class This is wrapper for RSA algorithm of openssl 3.0 libraryry.
*/
class EASYSSL_EXPORT RSASSL30: public EasySSL::ICrypto
class EASYSSL_EXPORT RSASSL: public EasySSL::ICrypto
{
public:
RSASSL30();
RSASSL();
EVP_PKEY *makeRawKeys() const override;
Features supportedFeatures() const override;
QSsl::KeyAlgorithm keyAlgorithm() const override;
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override;
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override;
@ -39,6 +40,7 @@ public:
* @return empty array.
*/
QByteArray encrypt(const QByteArray &message, const QByteArray &key) override;
};
}

View File

@ -1,199 +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 "rsassl11.h"
#include "qcryptographichash.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
namespace EasySSL {
RSASSL11::RSASSL11() {
}
bool RSASSL11::makeKeys(QByteArray &pubKey, QByteArray &privKey) const {
EVP_PKEY *pkey = EVP_PKEY_new();
if (!pkey) {
return false;
}
BIGNUM * bn = BN_new();
int rc = BN_set_word(bn, RSA_F4);
if (rc != 1) {
BN_free(bn);
EVP_PKEY_free(pkey);
return false;
}
RSA * rsa = RSA_new();
auto failed = [bn, rsa, pkey] () {
BN_free(bn);
RSA_free(rsa);
EVP_PKEY_free(pkey);
return false;
};
if (!RSA_generate_key_ex(rsa, 4196, bn, nullptr)) {
return failed();
}
q_check_ptr(rsa);
if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) {
return failed();
}
BIO *mem;
mem = BIO_new_mem_buf(pkey, -1); //pkey is of type char*
auto key = PEM_read_bio_PrivateKey(mem, NULL, NULL, 0);
BIO *private_key_bio = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPrivateKey(private_key_bio, rsa, NULL, NULL, 0, NULL, NULL);
char *private_key_data;
long private_key_size = BIO_get_mem_data(private_key_bio, &private_key_data);
privKey = QByteArray(private_key_data, private_key_size);
BIO_free(private_key_bio);
BIO *public_key_bio = BIO_new(BIO_s_mem());
PEM_write_bio_RSAPublicKey(public_key_bio, rsa);
char *public_key_data;
long public_key_size = BIO_get_mem_data(public_key_bio, &public_key_data);
pubKey = QByteArray(public_key_data, public_key_size);
BIO_free(public_key_bio);
return true;
}
ICrypto::Features RSASSL11::supportedFeatures() const {
return static_cast<ICrypto::Features>(Features::Encription | Features::Signing);
}
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<const unsigned char*>(hash.data()),
hash.size(), reinterpret_cast<unsigned char*>(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<const unsigned char*>(hash.data()),
hash.size(), reinterpret_cast<const unsigned char*>(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<const unsigned char*>(message.data()),
reinterpret_cast<unsigned char*>(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<const unsigned char*>(message.data()),
reinterpret_cast<unsigned char*>(encryptedMessage.data()),
rsaPublicKey, RSA_PKCS1_PADDING);
RSA_free(rsaPublicKey);
if (result == -1) {
perror("Error encrypting message");
return {};
}
return encryptedMessage;
}
}

View File

@ -1,45 +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 RSASSL11_H
#define RSASSL11_H
#include "global.h"
#include "icrypto.h"
namespace EasySSL {
/**
* @brief The RSASSL11 class This is wrapper of the openssl 1.1 implementation of the RSA alghorithm
*/
class EASYSSL_EXPORT RSASSL11: public EasySSL::ICrypto
{
public:
RSASSL11();
bool makeKeys(QByteArray &pubKey, QByteArray &privKey) const override;
Features supportedFeatures() const override;
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override;
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override;
/**
* @brief decrypt This method has empty implementation.
* @return empty array.
*/
QByteArray decrypt(const QByteArray &message, const QByteArray &key) override;
/**
* @brief encrypt This method has empty implementation.
* @return empty array.
*/
QByteArray encrypt(const QByteArray &message, const QByteArray &key) override;
};
}
#endif // RSASSL11_H

View File

@ -52,13 +52,10 @@ SelfSignedSertificate X509::create(const SslSrtData &certificateData) const {
if(result.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 {};
}
EVP_PKEY_free(pkey);
BIO_free_all(bp_private);
BIO * bp_public = BIO_new(BIO_s_mem());
q_check_ptr(bp_public);

View File

@ -8,7 +8,8 @@
#include <QtTest>
#include "cryptotest.h"
#include "authtest.h"
#include <easyssl/ecdsassl11.h>
#include "easyssl/rsassl.h"
#include <easyssl/ecdsassl.h>
// Use This macros for initialize your own test classes.
// Check exampletests
@ -35,7 +36,8 @@ private slots:
// BEGIN TESTS CASES
TestCase(authTest, AuthTest)
TestCase(cryptoTest, CryptoTest<EasySSL::ECDSASSL11>)
TestCase(cryptoTestESDSA, CryptoTest<EasySSL::ECDSASSL>)
TestCase(cryptoTestRSA, CryptoTest<EasySSL::RSASSL>)
// END TEST CASES

View File

@ -20,6 +20,18 @@ class CryptoTest: public Test, protected TestUtils
public:
void test() override {
// test short messges
testImpl("Test");
//test long messages
const int Mb = 1024 * 1024 * 1024; //1 mb
testImpl(QByteArray(Mb, 'c'));
} ;
void testImpl(const QByteArray& message) const {
// create a publick and private keys array.
QByteArray pub, priv;
TestClass crypto;
@ -29,19 +41,18 @@ public:
QVERIFY2(priv.size(), "Private key should be generated successfull");
if (crypto.supportedFeatures() & EasySSL::ICrypto::Features::Signing) {
auto siganture = crypto.signMessage("Test", priv);
auto siganture = crypto.signMessage(message, priv);
QVERIFY2(siganture.size(), "Siganture of the message should not be empty");
QVERIFY2(crypto.checkSign("Test", siganture, pub), "failed to check message");
QVERIFY2(crypto.checkSign(message, siganture, pub), "failed to check message");
}
if (crypto.supportedFeatures() & EasySSL::ICrypto::Features::Encription) {
auto encriptedMsg = crypto.encrypt("Test", pub);
auto encriptedMsg = crypto.encrypt(message, pub);
QVERIFY2(encriptedMsg.size(), "Encripted message should not be empty");
auto decryptedMsg = crypto.decrypt(encriptedMsg, priv);
QVERIFY2(decryptedMsg == "Test", "Failed to check message after decryption");
QVERIFY2(decryptedMsg == message, "Failed to check message after decryption");
}
} ;
}
};
#endif // CRYPTO_TEST_H

View File

@ -6,4 +6,3 @@
//#
#include "test.h"