mirror of
https://github.com/QuasarApp/easyssl.git
synced 2025-04-27 13:34:31 +00:00
drop support not EVP interfaces
This commit is contained in:
parent
a84929b069
commit
1ab0cc87bf
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
154
src/lib/src/public/easyssl/ecdsassl.cpp
Normal file
154
src/lib/src/public/easyssl/ecdsassl.cpp
Normal 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 {};
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -6,4 +6,3 @@
|
||||
//#
|
||||
|
||||
|
||||
#include "test.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user