O desenvolvimento de um sistema de encurtamento de links (Short URL) fundamenta-se na transformação de uma URL extensa em uma chave alfanumérica compacta. Diferente de identificadores puramente numéricos, os sistemas de links curtos utilizam frequentemente uma base superior à decimal, como a Base62, para maximizar o número de combinações possíveis com o menor número de caracteres.
Arquitetura e Requisitos do Algoritmo
Para que um algoritmo de encurtamento seja eficiente em um ambiente de produção, ele deve atender a critérios específicos de design:
- Unicidade: Cada URL longa deve, preferencialmente, resultar em uma chave única para evitar colisões de redirecionamento.
- Eficiência de Espaço: A chave gerada deve ser curta o suficiente para facilitar o compartilhamento em plataformas com limite de caracteres.
- Mapeamento Persistente: Como o processo de hash é geralmente unidirecional ou baseado em perdas, é necessário armazenar o par (chave_curta, url_original) em uma base de dados para permitir a recuperação posterior.
- Resolução de Conflitos: Estratégias como o uso de salts ou funções de hash secundárias devem ser aplicadas quando duas entradas diferentes geram a mesma saída.
Fluxo de Implementação
O processo técnico padrão envolve a aplicação de uma função de espalhamento (hash) seguida de uma conversão de base. Abaixo, apresenta-se uma implementação em C++ que utiliza a biblioteca OpenSSL para gerar um hash MD5 e converte os bytes resultantes em uma representação Base62.
#include <iostream>
#include <string>
#include <vector>
#include <openssl/md5.h>
/**
* Converte um valor numérico para uma representação alfanumérica (Base62).
* Utiliza o conjunto [0-9][a-z][A-Z].
*/
std::string converterParaBase62(unsigned long long valor) {
const std::string caracteres = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (valor == 0) return "0";
std::string resultado;
while (valor > 0) {
resultado.insert(0, 1, caracteres[valor % 62]);
valor /= 62;
}
return resultado;
}
/**
* Gera um identificador curto a partir de uma URL longa usando MD5.
*/
std::string gerarChaveCurta(const std::string& url_original) {
unsigned char digest[MD5_DIGEST_LENGTH];
MD5(reinterpret_cast<const unsigned char*>(url_original.c_str()), url_original.length(), digest);
// Extrai os primeiros 8 bytes do hash para formar um número de 64 bits
unsigned long long semente = 0;
for (int i = 0; i < 8; ++i) {
semente = (semente << 8) | digest[i];
}
return converterParaBase62(semente).substr(0, 7); // Retorna os primeiros 7 caracteres
}
int main() {
std::string url_alvo = "https://www.exemplo-de-dominio-longo.com/artigo/algoritmos-de-hash";
std::string chave = gerarChaveCurta(url_alvo);
std::cout << "URL Original: " << url_alvo << std::endl;
std::cout << "Chave Gerada: " << chave << std::endl;
return 0;
}
Utilizando SHA-256 para Maior Integridade
Embora o MD5 seja computacionalmente rápido, ele é suscetível a colisões. Em sistemas onde a segurança ou a integridade dos dados é crítica, o SHA-256 é a escolha recomednada. O exemplo a seguir demonstra como extrair um hash SHA-256 em formato hxeadecimal utilizando C++ e OpenSSL:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <openssl/sha.h>
std::string calcularSHA256(const std::string& entrada) {
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX contexto_sha;
SHA256_Init(&contexto_sha);
SHA256_Update(&contexto_sha, entrada.c_str(), entrada.size());
SHA256_Final(hash, &contexto_sha);
std::stringstream hex_stream;
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
hex_stream << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(hash[i]);
}
return hex_stream.str();
}
int main() {
std::string payload = "Dados para encriptação via SHA-256";
std::string hash_resultado = calcularSHA256(payload);
std::cout << "Entrada: " << payload << std::endl;
std::cout << "Hash SHA-256: " << hash_resultado << std::endl;
return 0;
}
Considerações Técnicas de Compilação
Ao trabalhar com bibliotecas criptográficas como a OpenSSL em sistemas baseados em Unix/Linux (como Ubuntu ou Debian), é necessário garantir que os cabeçalhos de desenvolvimento estejam instalados. Para compilar os exemplos acima utilizando o g++, deve-se vincular explicitamente a biblioteca de criptografia:
g++ -o encurtador_link main.cpp -lcrypto
O parâmetro -lcrypto instrui o linker a incluir as funções necessárias para o cálculo de MD5 e SHA-256. Em aplicações de larga escala, o hash gerado costuma ser truncado e armazenado em um banco de dados NoSQL (como Redis ou MongoDB) para garantir latência mínima durante a operação de redirecionamanto.