Como Automatizar Criptografia com script C++

🚀 Da série C++ como Shell Script.


Como Automatizar Criptografia com script C++


Dia desse eu notei que havia compactado diversos arquivos como backup em uma mídia de DVD(os DVDs tinham pelo menos uns 15 anos) e também havia criptografado todos eles com GnuPG.

E todos esses arquivos tinham a mesma senha para o .gpg e eu precisava saber o que havia dentro deles.

Como muitos eram arquivos de muito tempo, haviam até arquivos de mais 5GB =)

Eu já ia começar a escrever o código shell script para descriptografar e descompactar todos de uma vez só pra descobrir o que havia dentro deles.

Mas, lembrei do comando limpeza e isso poderia ser rápido em escrever o código, mas iria me tomar muito tempo na execução.

Eu poderia usar a API do GPGME e criar ele diretamente via código C++, mas não se trata de uma aplicação completa, é só um scriptzinho básico!!!

Então, decidi, mais uma vez, criar um script que poderia ser feito com GNU Bash em C++.


Introdução

Primeiramente, o que é o GnuPG?

GnuPG é o acrônimo/sigla para: “GNU Privacy Guard (GnuPG ou GPG)” é um software livre alternativo ao conjunto de softwares criptográficos PGP da Symantec.

GnuPG é parte da Free Software Foundation e do Projeto GNU. Além disso, ele recebeu grande patrocínio do Governo Alemão.

Instalação do GnuPG

Use o gerenciador de pacotes do seu sistema operacional, exemplos:

winget install --id=GnuPG.GnuPG  -e

Via: https://winstall.app/apps/GnuPG.GnuPG ou https://winget.run/pkg/GnuPG/GnuPG.

brew install gnupg

Via: https://formulae.brew.sh/formula/gnupg

  • No Ubuntu
sudo apt install gnupg

Uso básico do GnuPG

Suponhamos que você possua uma pasta de nome files/ e compactou ela em formato .zip e ele se tornou: files.zip.

Se você quiser proteger com senha e criptografia, basta rodar o comando:

gpg -c files.zip

Em seguida lhe será solitada uma senha e a confirmação da senha para criar o arquivo: files.zip.gpg. Só quem tem acesso a essa senha conseguirá descriptografar.

O legal(e perigoso) é que você pode inserir a senha via linha de comando, tanto para criptografar quanto para descriptografar e isso pode lhe poupar tempo de ficar toda hora entrando no modo interativo e digitar senha por senha…

E foi pensando em não sofrer esse tédio/estresse repetitivo que eu tive essa ideia!


Criando o script C++

Antes de mais nada esses arquivos do tipo .gpg estavam misturados com outros tipos de arquivos e eu não queria filtrar, pois manter onde eles estavam era o ideal antes de mandar eles pro meu server local aqui em casa. Então, vão incluir também o cabeçalho <filesystem> para tratar esses arquivos:

#include <iostream>
#include <filesystem>
#include <vector>

namespace fs = std::filesystem;


int main(){
  // Indicar o caminho da pasta, nesse caso, onde está o script
  std::string directory_path = "./";
  std::vector<std::string> gpg_files {};

  // Verificar se o diretório existe
  if (!fs::exists(directory_path) || !fs::is_directory(directory_path)) {
    std::cerr << "O diretório não existe ou não válido." << std::endl;
    return 1;
  }

  // Iterar sobre os arquivos no diretório
  for (const auto& entry : fs::directory_iterator(directory_path)) {
    if (entry.is_regular_file() && entry.path().extension() == ".gpg") {
      gpg_files.push_back(entry.path().filename().string());
    }
  }

  // Opcional
  // Exibe os nomes dos arquivos .gpg encontrados
  std::cout << "Arquivos .gpg encontrados:" << std::endl;
  for (const auto& file : gpg_files) {
    std::cout << file << ' ';
  }
  std::cout.put('\n');

  // Definir a senha para todos os arquivos
  std::string str = "SENHA_SECRETA";
}

Agora é só rodar o comando para descriptografar os arquivos encontrados e listados:

  for (const auto& file : gpg_files) {
    std::string com = "gpg --yes --batch --passphrase=" + str + " " + file + " 2>/dev/null";
    std::cout << "Descriptografando: " << file << std::endl;
    std::system(com.data());
  }

Eu ainda iria descompactar eles automaticamente adicionando ao loop, mas desisti, nesse caso usando o comando extract porque os tipos poderiam se variados: zip, rar, tar.gz,…

// filename se iguala a file para separar a lógica
std::string filename = file;

// Remover o .gpg do nome do arquivo
if (filename.size() >= 4) {
  filename = filename.substr(0, filename.size() - 4);
}

// Executar
std::string extract = "/usr/bin/extract " + filename;
std::cout << extract << std::endl;
std::system(extract.data());

Eu desisti de fazer isso porque isso iria misturar minha tarefa específica, e depois cheguei até tentar, mas o resultado não foi tão bom.

O código completo ficou: decript.cpp

#include <iostream>
#include <filesystem>
#include <vector>

namespace fs = std::filesystem;

int main(){
  // Indicar o caminho da pasta, nesse caso, onde está o script
  std::string directory_path = "./";
  std::vector<std::string> gpg_files {};

  // Verificar se o diretório existe
  if (!fs::exists(directory_path) || !fs::is_directory(directory_path)) {
    std::cerr << "O diretório não existe ou não válido." << std::endl;
    return 1;
  }

  // Iterar sobre os arquivos no diretório
  for (const auto& entry : fs::directory_iterator(directory_path)) {
    if (entry.is_regular_file() && entry.path().extension() == ".gpg") {
      gpg_files.push_back(entry.path().filename().string());
    }
  }

  // Opcional
  // Exibe os nomes dos arquivos .gpg encontrados
  std::cout << "Arquivos .gpg encontrados:" << std::endl;
  for (const auto& file : gpg_files) {
    std::cout << file << ' ';
  }
  std::cout.put('\n');

  // Definir a senha para todos os arquivos
  std::string str = "SENHA_SECRETA";
}

Se quiser fazer o mesmo script, mas para criar arquivos .gpg com senha dinamicamente, substitua com por:

std::string com = "gpg --yes --batch --passphrase=" + str + " -c " + file;

Note o uso do -c.


Script final

decript.cpp

#include <iostream>
#include <filesystem>
#include <vector>

namespace fs = std::filesystem;

int main(){
  std::string directory_path = "./";
  std::vector<std::string> gpg_files {};

  if (!fs::exists(directory_path) || !fs::is_directory(directory_path)) {
    std::cerr << "O diretório não existe ou não válido." << std::endl;
    return 1;
  }

  for (const auto& entry : fs::directory_iterator(directory_path)) {
    if (entry.is_regular_file() && entry.path().extension() == ".gpg") {
      gpg_files.push_back(entry.path().filename().string());
    }
  }

  std::cout << "Arquivos .gpg encontrados:" << std::endl;
  for (const auto& file : gpg_files) {
    std::cout << file << ' ';
  }
  std::cout << "\n\n";

  std::string str = "SENHA_SECRETA";

  for (const auto& file : gpg_files) {
    std::string com = "gpg --yes --batch --passphrase=" + str + " " + file + " 2>/dev/null";
    std::cout << "Descriptografando: " << file << std::endl;
    int run = std::system(com.data());
    if(run != 0){
      std::cerr << "Failed to run: " << com << std::endl;
    }
  }

  return EXIT_SUCCESS;
}

Se quiser garantir que não há violação de memória, compile:

g++ -g -Wpedantic -Wall -Werror -fsanitize=address decript.cpp

Mas, para rodar, adicione mais velocidade na execução:

g++ -Ofast decript.cpp

Depois é só rodar: ./a.out.

Para extrair eu usei um script em Terlang:

vim unzip.ter

auto files = {"TheDir.tar.gz", "MyFolder.zip", "BigData.tar.gz"}
auto filesSize = 3

for(auto i = 0; i < filesSize; ++i){
  output("Descompactando: " + files[i])
  exec("extract " + files[i])
}

Para mais informações sobre Terlang, conheça nosso Curso de Como Criar Sua Própria Linguagem de Programação:

https://terminalroot.com.br/mylang


E assim, eu fiz, do meu jeito, uma tarefa que poderia me levar muito tempo, de forma rápida e prática! 😃


cpp cppdaily gnupg shellscript criptografia


Compartilhe


Nosso canal no Youtube

Inscreva-se


Marcos Oliveira

Marcos Oliveira

Desenvolvedor de software
https://github.com/terroo


Crie Aplicativos Gráficos para Linux e Windows com C++

Aprenda C++ Moderno e crie Games, Programas CLI, GUI e TUI de forma fácil.

Saiba Mais

Receba as novidades no seu e-mail!

Após cadastro e confirmação do e-mail, enviaremos semanalmente resumos e também sempre que houver novidades por aqui para que você mantenha-se atualizado!