Implementação de Criptografia RSA com OpenSSL no Qt

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.

Tags: openssl rsa Qt encryption C++

Publicado em 7-12 05:44