added rsa implementation for openssl 1.1

This commit is contained in:
Andrei Yankovich 2023-07-04 17:12:16 +02:00
parent cc26a5cae4
commit c472d04c87
4 changed files with 203 additions and 44 deletions

View File

@ -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 <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/types.h>
#include <QVector>
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<unsigned char> data(length);
BN_bn2mpi(num, data.data());
QByteArray result;
result.insert(0, reinterpret_cast<char*>(data.data()), data.length());
return result;
}
BIGNUM *EasySSLUtils::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;
}
}

View File

@ -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 <openssl/types.h>
#include <QByteArray>
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);
};
};

View File

@ -17,15 +17,10 @@
#include <QDataStream>
#include <QIODevice>
#include <QVector>
#include <easysslutils.h>
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<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;
}
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,

View File

@ -7,6 +7,7 @@
#include "rsassl11.h"
#include "qcryptographichash.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
@ -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<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;
}
}