project.pro
QT += core gui widgets
CONFIG += c++11
TARGET = CriptoMaster
TEMPLATE = app
SOURCES += main.cpp
LIBS += -lcrypto
main.cpp
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QTextEdit>
#include <QLabel>
#include <QTabWidget>
#include <QMessageBox>
// OpenSSL Headers
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/crypto.h>
/**
* CRIPTOGRAFAR: Gera Salt e IV aleatórios, deriva a chave e empacota tudo em Base64.
*/
QByteArray encrypt(const QByteArray &data, const QString &password) {
if (data.isEmpty() || password.isEmpty()) return QByteArray();
unsigned char key[32];
unsigned char iv[16];
unsigned char salt[8];
// 1. Gerar Salt e IV aleatórios (Segurança Máxima)
RAND_bytes(salt, sizeof(salt));
RAND_bytes(iv, sizeof(iv));
// 2. Derivar chave de 256 bits da senha usando o Salt
if (PKCS5_PBKDF2_HMAC(password.toUtf8().constData(), password.length(),
salt, sizeof(salt), 100000, EVP_sha256(), 32, key) != 1) {
return QByteArray();
}
// 3. Configurar AES-256-CBC
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
QByteArray ciphertext;
ciphertext.resize(data.size() + EVP_MAX_BLOCK_LENGTH);
int len = 0, ciphertextLen = 0;
EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, iv);
EVP_EncryptUpdate(ctx, (unsigned char*)ciphertext.data(), &len, (unsigned char*)data.data(), data.size());
ciphertextLen = len;
EVP_EncryptFinal_ex(ctx, (unsigned char*)ciphertext.data() + len, &len);
ciphertextLen += len;
EVP_CIPHER_CTX_free(ctx);
ciphertext.resize(ciphertextLen);
// 4. Empacotamento: SALT(8) + IV(16) + CIPHERTEXT
QByteArray finalPackage;
finalPackage.append((char*)salt, 8);
finalPackage.append((char*)iv, 16);
finalPackage.append(ciphertext);
// Limpeza de segurança
OPENSSL_cleanse(key, 32);
OPENSSL_cleanse(iv, 16);
return finalPackage.toBase64();
}
/**
* DESCRIPTOGRAFAR: Extrai Salt e IV do pacote, deriva a chave e recupera o texto.
*/
QByteArray decrypt(const QByteArray &base64Data, const QString &password) {
QByteArray fullData = QByteArray::fromBase64(base64Data);
// Verificação mínima: Salt(8) + IV(16) + pelo menos 1 bloco de dados
if (fullData.size() < 25) return QByteArray();
unsigned char salt[8];
unsigned char iv[16];
unsigned char key[32];
// 1. Extrair os componentes do pacote
memcpy(salt, fullData.constData(), 8);
memcpy(iv, fullData.constData() + 8, 16);
QByteArray ciphertext = fullData.mid(24);
// 2. Reconstruir a chave usando o Salt extraído do pacote
if (PKCS5_PBKDF2_HMAC(password.toUtf8().constData(), password.length(),
salt, 8, 100000, EVP_sha256(), 32, key) != 1) {
return QByteArray();
}
// 3. Configurar Descriptografia
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
QByteArray decryptedText;
decryptedText.resize(ciphertext.size() + EVP_MAX_BLOCK_LENGTH);
int len = 0, decryptedLen = 0;
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, iv);
EVP_DecryptUpdate(ctx, (unsigned char*)decryptedText.data(), &len, (unsigned char*)ciphertext.data(), ciphertext.size());
decryptedLen = len;
// Se a senha estiver errada, o Final_ex falhará devido ao padding
int ret = EVP_DecryptFinal_ex(ctx, (unsigned char*)decryptedText.data() + len, &len);
decryptedLen += len;
EVP_CIPHER_CTX_free(ctx);
OPENSSL_cleanse(key, 32);
if (ret != 1) return QByteArray(); // Falha na segurança (senha errada)
decryptedText.resize(decryptedLen);
return decryptedText;
}
// --- Interface Gráfica ---
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QTabWidget tabs;
tabs.setWindowTitle("CriptoMaster AES-256");
tabs.setMinimumSize(600, 450);
// Aba Criptografar
QWidget *encPage = new QWidget();
QVBoxLayout *encLayout = new QVBoxLayout(encPage);
QTextEdit *encInput = new QTextEdit();
QLineEdit *encPass = new QLineEdit(); encPass->setEchoMode(QLineEdit::Password);
QTextEdit *encOutput = new QTextEdit(); encOutput->setReadOnly(true);
QPushButton *encBtn = new QPushButton("Criptografar e Limpar Origem");
encLayout->addWidget(new QLabel("Texto para Trancar:")); encLayout->addWidget(encInput);
encLayout->addWidget(new QLabel("Senha:")); encLayout->addWidget(encPass);
encLayout->addWidget(encBtn);
encLayout->addWidget(new QLabel("Resultado Base64 (Salve isso!):")); encLayout->addWidget(encOutput);
// Aba Descriptografar
QWidget *decPage = new QWidget();
QVBoxLayout *decLayout = new QVBoxLayout(decPage);
QTextEdit *decInput = new QTextEdit();
QLineEdit *decPass = new QLineEdit(); decPass->setEchoMode(QLineEdit::Password);
QTextEdit *decOutput = new QTextEdit(); decOutput->setReadOnly(true);
QPushButton *decBtn = new QPushButton("Descriptografar");
decLayout->addWidget(new QLabel("Código Base64:")); decLayout->addWidget(decInput);
decLayout->addWidget(new QLabel("Senha:")); decLayout->addWidget(decPass);
decLayout->addWidget(decBtn);
decLayout->addWidget(new QLabel("Texto Revelado:")); decLayout->addWidget(decOutput);
// Logica dos Botões
QObject::connect(encBtn, &QPushButton::clicked, [&]() {
QByteArray res = encrypt(encInput->toPlainText().toUtf8(), encPass->text());
if(!res.isEmpty()) {
encOutput->setPlainText(res);
// Limpa memória sensível do campo de entrada
QString temp = encInput->toPlainText();
OPENSSL_cleanse((void*)temp.utf16(), temp.capacity() * 2);
encInput->clear();
}
});
QObject::connect(decBtn, &QPushButton::clicked, [&]() {
QByteArray res = decrypt(decInput->toPlainText().toUtf8(), decPass->text());
if (res.isEmpty()) {
QMessageBox::critical(&tabs, "Erro de Chave", "Senha incorreta ou dados corrompidos.");
decOutput->clear();
} else {
decOutput->setPlainText(QString::fromUtf8(res));
OPENSSL_cleanse((void*)res.data(), res.capacity());
}
});
tabs.addTab(encPage, "Criptografar");
tabs.addTab(decPage, "Descriptografar");
tabs.show();
return a.exec();
}
sudo apt install build-essential libssl-dev qtbase5-dev qt5-qmake
qmake project.pro
make