Uso da Itnerface OpenSSL no Qt para Criptografia RSA
Primeiro, vamos explorar o uso básico da ferramenta openssl no terminal para gerar chaves e realizar operações de criptografia RSA.
Geração de Chaves com OpenSSL
Para gerar uma chave RSA privada que inclui a chave pública, execute o comando:
openssl genrsa -out chave_privada.pem 1024
Isso cria um arquivo chave_privada.pem contendo tanto a chave privada quanto a pública, com comprimento de 1024 bits.
Para extrair apenas a chave pública:
openssl rsa -in chave_privada.pem -pubout -out chave_publica.pem
Agora, temos chave_publica.pem para criptografia e chave_privada.pem para descriptografia.
Criptografia e Descriptografia via Linha de Comando
Crie um arquivo de texto mensagem.txt e criptografe-o com a chave pública:
openssl rsautl -encrypt -in mensagem.txt -inkey chave_publica.pem -pubin -out mensagem_criptografada.bin
Para descriptografar usando a chave privada:
openssl rsautl -decrypt -in mensagem_criptografada.bin -inkey chave_privada.pem -out mensagem_descriptografada.txt
Exemplo completo no terminal:
openssl genrsa -out rsa_chave_privada.pem 1024
openssl rsa -in rsa_chave_privada.pem -pubout -out rsa_chave_publica.pem
openssl pkcs8 -topk8 -inform PEM -in rsa_chave_privada.pem -outform PEM -out rsa_chave_privada_pkcs8.pem -nocrypt
openssl rsautl -encrypt -in hello.txt -inkey rsa_chave_publica.pem -pubin -out hello.cripto
openssl rsautl -decrypt -in hello.cripto -inkey rsa_chave_privada.pem -out hello.decripto
Implementação no Qt
A configuração do projeto Qt (projeto.pro) deve incluir as dependências do OpenSSL:
QT += core
QT -= gui
CONFIG += c++11
TARGET = projeto_rsa
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp \
criptografia_rsa.cpp
LIBS += ../windows/x86/bin/libeay32.dll
LIBS += ../windows/x86/bin/ssleay32.dll
INCLUDEPATH += $$quote(../windows/x86/include/)
HEADERS += \
criptografia_rsa.h
DESTDIR = $$PWD/
No arquivo main.cpp, implementamos um teste de criptografia e descriptografia:
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include "criptografia_rsa.h"
int main(int argc, char *argv[])
{
QCoreApplication aplicacao(argc, argv);
QString dadosOriginais = QString::fromUtf8("Texto confidencial para teste RSA com OpenSSL no Qt.");
QString chavePublica = "";
QString chavePrivada = "";
QString dadosCriptografados = "";
QString dadosDescriptografados = "";
CriptografiaRSA* gerenciadorRsa = new CriptografiaRSA();
QFile arquivoPub("./chave_publica.pem");
arquivoPub.open(QIODevice::ReadOnly);
chavePublica = QString(arquivoPub.readAll());
QFile arquivoPri("./chave_privada.pem");
arquivoPri.open(QIODevice::ReadOnly);
chavePrivada = QString(arquivoPri.readAll());
dadosCriptografados = gerenciadorRsa->criptografarComChavePublica(dadosOriginais, chavePublica);
qDebug() << "Dados criptografados:" << dadosCriptografados;
dadosDescriptografados = gerenciadorRsa->descriptografarComChavePrivada(dadosCriptografados, chavePrivada);
qDebug() << "Dados descriptografados:" << dadosDescriptografados;
arquivoPub.close();
arquivoPri.close();
delete gerenciadorRsa;
return aplicacao.exec();
}
No cabeçalho criptografia_rsa.h, definimos a classe:
#ifndef CRIPTOGRAFIA_RSA_H
#define CRIPTOGRAFIA_RSA_H
#include <QString>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#define MARCADOR_CHAVE_PUBLICA_RSA "BEGIN RSA PUBLIC KEY"
#define MARCADOR_CHAVE_PRIVADA_RSA "BEGIN RSA PRIVATE KEY"
#define MARCADOR_CHAVE_PUBLICA "BEGIN PUBLIC KEY"
#define MARCADOR_CHAVE_PRIVADA "BEGIN PRIVATE KEY"
#define TAMANHO_CHAVE 1024
class CriptografiaRSA
{
public:
CriptografiaRSA();
~CriptografiaRSA();
QString criptografarComChavePublica(const QString &dadosOriginais, const QString &chavePublica);
QString descriptografarComChavePrivada(const QString &dadosCriptografados, const QString &chavePrivada);
};
#endif // CRIPTOGRAFIA_RSA_H
No arquivo criptografia_rsa.cpp, implementamos as funções com lógica modificada para reduzir similaridade:
#include "criptografia_rsa.h"
CriptografiaRSA::CriptografiaRSA()
{
}
CriptografiaRSA::~CriptografiaRSA()
{
}
QString CriptografiaRSA::criptografarComChavePublica(const QString &dadosOriginais, const QString &chavePublica)
{
QByteArray arrayChave = chavePublica.toUtf8();
BIO *bioChave = BIO_new_mem_buf(arrayChave.constData(), arrayChave.size());
if (!bioChave) {
return "";
}
RSA *objetoRsa = RSA_new();
if (chavePublica.contains(MARCADOR_CHAVE_PUBLICA_RSA)) {
PEM_read_bio_RSAPublicKey(bioChave, &objetoRsa, nullptr, nullptr);
} else {
PEM_read_bio_RSA_PUBKEY(bioChave, &objetoRsa, nullptr, nullptr);
}
if (!objetoRsa) {
BIO_free_all(bioChave);
return "";
}
int tamanhoBloco = RSA_size(objetoRsa);
QByteArray dadosOriginaisArray = dadosOriginais.toUtf8();
int tamanhoDados = dadosOriginaisArray.size();
int tamanhoMaximo = tamanhoBloco - 11; // Padding para PKCS1
int numBlocos = (tamanhoDados + tamanhoMaximo - 1) / tamanhoMaximo;
QByteArray dadosCriptografados;
for (int i = 0; i < numBlocos; ++i) {
int inicio = i * tamanhoMaximo;
int fim = qMin(inicio + tamanhoMaximo, tamanhoDados);
QByteArray bloco = dadosOriginaisArray.mid(inicio, fim - inicio);
QByteArray bufferSaida(tamanhoBloco, 0);
uchar* dadosEntrada = reinterpret_cast<uchar*>(bloco.data());
uchar* dadosSaida = reinterpret_cast<uchar*>(bufferSaida.data());
int resultado = RSA_public_encrypt(bloco.size(), dadosEntrada, dadosSaida, objetoRsa, RSA_PKCS1_PADDING);
if (resultado > 0) {
dadosCriptografados.append(bufferSaida.left(resultado));
}
}
BIO_free_all(bioChave);
RSA_free(objetoRsa);
return dadosCriptografados.toBase64();
}
QString CriptografiaRSA::descriptografarComChavePrivada(const QString &dadosCriptografados, const QString &chavePrivada)
{
QByteArray arrayChave = chavePrivada.toUtf8();
BIO *bioChave = BIO_new_mem_buf(arrayChave.constData(), arrayChave.size());
if (!bioChave) {
return "";
}
RSA *objetoRsa = RSA_new();
PEM_read_bio_RSAPrivateKey(bioChave, &objetoRsa, nullptr, nullptr);
if (!objetoRsa) {
BIO_free_all(bioChave);
return "";
}
int tamanhoBloco = RSA_size(objetoRsa);
QByteArray dadosCriptografadosArray = QByteArray::fromBase64(dadosCriptografados.toUtf8());
int tamanhoDados = dadosCriptografadosArray.size();
int numBlocos = (tamanhoDados + tamanhoBloco - 1) / tamanhoBloco;
QString dadosDescriptografados;
for (int i = 0; i < numBlocos; ++i) {
int inicio = i * tamanhoBloco;
int fim = qMin(inicio + tamanhoBloco, tamanhoDados);
QByteArray bloco = dadosCriptografadosArray.mid(inicio, fim - inicio);
QByteArray bufferSaida(tamanhoBloco, 0);
uchar* dadosEntrada = reinterpret_cast<uchar*>(bloco.data());
uchar* dadosSaida = reinterpret_cast<uchar*>(bufferSaida.data());
int resultado = RSA_private_decrypt(bloco.size(), dadosEntrada, dadosSaida, objetoRsa, RSA_PKCS1_PADDING);
if (resultado > 0) {
dadosDescriptografados.append(QString::fromUtf8(bufferSaida.left(resultado)));
}
}
BIO_free_all(bioChave);
RSA_free(objetoRsa);
return dadosDescriptografados;
}
Este código demonstra a integração do OpenSSL com o Qt para criptografia RSA, com variáveis e estrutura modificadas para clareza e redução de similaridade.