10#include "qcryptographichash.h"
11#include <openssl/bn.h>
12#include <openssl/evp.h>
13#include <openssl/pem.h>
14#include <openssl/rsa.h>
26 EVP_PKEY *pkey =
nullptr;
27 EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(
nullptr,
"RSA",
nullptr);
28 EVP_PKEY_keygen_init(pctx);
30 if (EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, _bits) <= 0) {
34 EVP_PKEY_generate(pctx, &pkey);
35 EVP_PKEY_CTX_free(pctx);
45 return QSsl::KeyAlgorithm::Rsa;
52 auto rsaPrivateKey = PEM_read_bio_PrivateKey(pkey,
nullptr,
nullptr,
nullptr);
56 qCritical() <<
"Error reading private key";
61 EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
62 if (mdctx ==
nullptr) {
67 if (EVP_DigestSignInit(mdctx,
nullptr, EVP_sha256(),
nullptr, rsaPrivateKey) != 1) {
69 EVP_MD_CTX_free(mdctx);
73 auto hash = QCryptographicHash::hash(inputData,
74 QCryptographicHash::Sha256);
77 if (EVP_DigestSignUpdate(mdctx, hash.data(), hash.size()) != 1) {
79 EVP_MD_CTX_free(mdctx);
83 size_t signatureLength = EVP_PKEY_size(rsaPrivateKey);
84 signature.resize(signatureLength);
87 if (EVP_DigestSignFinal(mdctx,
reinterpret_cast<unsigned char*
>(signature.data()), &signatureLength) != 1) {
89 EVP_MD_CTX_free(mdctx);
93 signature.resize(signatureLength);
95 EVP_MD_CTX_free(mdctx);
99bool RSASSL::checkSign(
const QByteArray &inputData,
const QByteArray &signature,
const QByteArray &key)
const {
100 EVP_MD_CTX* mdctx = EVP_MD_CTX_new();
101 if (mdctx ==
nullptr) {
106 auto rsaPublickKey = PEM_read_bio_PUBKEY(pkey,
nullptr,
nullptr,
nullptr);
110 if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, rsaPublickKey) != 1) {
112 EVP_MD_CTX_free(mdctx);
116 auto hash = QCryptographicHash::hash(inputData,
117 QCryptographicHash::Sha256);
120 if (EVP_DigestVerifyUpdate(mdctx, hash.data(), hash.size()) != 1) {
122 EVP_MD_CTX_free(mdctx);
127 int verificationResult = EVP_DigestVerifyFinal(mdctx,
128 reinterpret_cast<const unsigned char*
>(signature.data()),
131 EVP_MD_CTX_free(mdctx);
133 return verificationResult == 1;
139 auto rsaPrivateKey = PEM_read_bio_PrivateKey(pkey,
nullptr,
nullptr,
nullptr);
142 if (!rsaPrivateKey) {
143 qCritical() <<
"Error reading private key";
148 const long long maxDencryptedSize = EVP_PKEY_size(rsaPrivateKey);
149 if (message.length() % maxDencryptedSize) {
150 qCritical() <<
"Error wrong encrypted data size.";
151 qCritical() <<
"Your key requir size multiple " << maxDencryptedSize;
157 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(rsaPrivateKey,
nullptr);
158 if (ctx ==
nullptr) {
159 EVP_PKEY_free(rsaPrivateKey);
163 if (EVP_PKEY_decrypt_init(ctx) <= 0) {
166 EVP_PKEY_CTX_free(ctx);
167 EVP_PKEY_free(rsaPrivateKey);
171 if (EVP_PKEY_CTX_set_rsa_padding(ctx, getRawOpenSSLPandingValue(_padding)) <= 0) {
173 EVP_PKEY_CTX_free(ctx);
174 EVP_PKEY_free(rsaPrivateKey);
178 QByteArray decryptedData;
180 for (
int index = 0; index < message.size(); index += maxDencryptedSize) {
182 QByteArray decryptedDataPart(maxDencryptedSize, 0);
183 size_t realDecryptedDataPartSize = maxDencryptedSize;
184 if (EVP_PKEY_decrypt(ctx,
185 reinterpret_cast<unsigned char*
>(decryptedDataPart.data()),
186 &realDecryptedDataPartSize,
187 reinterpret_cast<const unsigned char*
>(&(message.constData()[index])),
188 maxDencryptedSize) <= 0) {
191 EVP_PKEY_CTX_free(ctx);
192 EVP_PKEY_free(rsaPrivateKey);
196 decryptedData += decryptedDataPart.left(realDecryptedDataPartSize);
199 EVP_PKEY_CTX_free(ctx);
200 EVP_PKEY_free(rsaPrivateKey);
201 return decryptedData;
207 auto rsaPublicKey = PEM_read_bio_PUBKEY(pkey,
nullptr,
nullptr,
nullptr);
211 qCritical() <<
"Error reading public key";
216 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(rsaPublicKey,
nullptr);
217 if (ctx ==
nullptr) {
219 EVP_PKEY_free(rsaPublicKey);
223 if (EVP_PKEY_encrypt_init(ctx) <= 0) {
225 EVP_PKEY_CTX_free(ctx);
226 EVP_PKEY_free(rsaPublicKey);
230 if (EVP_PKEY_CTX_set_rsa_padding(ctx, getRawOpenSSLPandingValue(_padding)) <= 0) {
232 EVP_PKEY_CTX_free(ctx);
233 EVP_PKEY_free(rsaPublicKey);
237 const long long maxEncryptedSize = EVP_PKEY_size(rsaPublicKey);
238 QByteArray encryptedData;
240 for (
int index = 0; index < message.size();) {
242 QByteArray encryptedDataPart(maxEncryptedSize, 0);
243 size_t realEncryptedDataPartSize = 0;
244 int currentPartSize = std::min(message.length() - index, maxEncryptedSize - getPandingSize(_padding)) ;
245 if (EVP_PKEY_encrypt(ctx,
246 reinterpret_cast<unsigned char*
>(encryptedDataPart.data()),
247 &realEncryptedDataPartSize,
248 reinterpret_cast<const unsigned char*
>(&(message.constData()[index])),
249 currentPartSize) <= 0) {
252 EVP_PKEY_CTX_free(ctx);
253 EVP_PKEY_free(rsaPublicKey);
257 encryptedData += encryptedDataPart.left(realEncryptedDataPartSize);
258 index += currentPartSize;
261 EVP_PKEY_CTX_free(ctx);
262 EVP_PKEY_free(rsaPublicKey);
263 return encryptedData;
271 _padding = newPadding;
274int RSASSL::getRawOpenSSLPandingValue(RSAPadding panding) {
276 case NO_PADDING:
return RSA_NO_PADDING;
277 case PKCS1_OAEP_PADDING:
return RSA_PKCS1_OAEP_PADDING;
278 case PKCS1_PADDING:
return RSA_PKCS1_PADDING;
285int RSASSL::getPandingSize(RSAPadding panding) {
287 case PKCS1_OAEP_PADDING:
return 42;
288 case PKCS1_PADDING:
return 11;
static BIO * byteArrayToBio(const QByteArray &byteArray)
byteArrayToBio This method creates the BIO struct from the Qt QByteArray object.
static void printlastOpenSSlError()
printlastOpenSSlError This method prints the latest ssl error message.
Features
The Features enum this is list of the supported description features.
@ Encryption
Encryption and decryption data.
@ Signing
Signin and check sign of the data.
Features supportedFeatures() const override
supportedFeatures This method should return supported featurs of the current encryption algorithm
void * makeRawKeys() const override
makeKeys This method generate the public and private keys of the ECDSA.
RSABits bits() const
bits return cuurrent rsa keys size mode. Using oly for generate keys.
void setBits(RSABits newBits)
setBits sets new value of the rsa key generator.
QByteArray decrypt(const QByteArray &message, const QByteArray &key) override
decrypt This method has empty implementation.
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override
signMessage This method should be sign the message using the key.
QSsl::KeyAlgorithm keyAlgorithm() const override
keyAlgorithm This method should be return Qt Key algorithm (needed for generate cetrificates....
RSAPadding padding() const
padding This is mode of pending data before icnription.
void setPadding(RSAPadding newPadding)
setPadding This method sets new mode for encryption pendong.
QByteArray encrypt(const QByteArray &message, const QByteArray &key) override
encrypt This method has empty implementation.
RSASSL(RSAPadding padding=PKCS1_OAEP_PADDING)
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override
checkSign This method should be check signature of the message using the key.