Código C para gerar hashes DES e MD5
Publicado por Elgio Schlemer (última atualização em 18/01/2010)
[ Hits: 18.401 ]
Homepage: https://profelgio.duckdns.org/~elgio
Este código escrito em C para Linux serve apenas para gerar um hash DES ou MD5 no formato utilizado pelo Unix/Linux. É o mesmo que pode ser encontrado no /etc/shadow de qualquer máquina Linux.
O assunto hashes foi abordado no artigo: http://www.vivaolinux.com.br/artigo/Armazenamento-de-senhas-no-Linux/
Este programa em C é parte do artigo, inicialmente publicado em minha página pessoal e agora disponibilizado no Viva o Linux.
O código está vastamente comentado, inclusive na parte de geração randômica de salt number.
/* * TÍTULO: Código C para gerar hashes DES e MD5 */ #include <stdio.h> #include <unistd.h> #include <string.h> /* Este codigo precisa ser compilado no Linux da seguinte forma * * gcc hashLinux.c -lcrypt -o hashLinux * * E executado: * ./hashLinux * * */ /* * Existe uma função na lib do Linux para gerar hahes, a crypt. Basta fornecer * o salt number e a senha que ela retorna o hash * * A lógica para geração de hahes é a seguinte: * - usuário digita uma senha * - sistema sorteia os caracteres de salt number * - gera-se o hash correspondente * * Para entender o que é salt number e a sua extrema relevância, leia o artigo * http://www.vivaolinux.com.br/artigo/Armazenamento-de-senhas-no-Linux/ * * Veja que facilmente poderia-se converter este programa para * verificar se a senha confere. Apenas NãO TERIA a etapa de sortear o salt number * * Para verificar se uma senha digitada confere as etapas seriam estas: * - usuário digita seu login * - pelo login, o programa já vai no /etc/shadow e pega o hash deste login, * digamos, dG5OdAa8n/36k no DES ou $1$23OEoGVk$4jcc8phmHcGv.dpNkBGtu0 no MD5 * * - se for DES, o sistema pega o sal number que está no shadow (dG do dG5OdAa8n/36k) * * - chama a função crypt(senhaFornecida, "dG") e verifica se o resultado gerado * bate com "dG5OdAa8n/36k". Beteu? Senha confere * * - Se for MD5, a mesma coisa, pega o salt number do hash do arquivo /etc/shadow * (exemplo: $1$23OEoGVk$4jcc8phmHcGv.dpNkBGtu0 ==> salt = "$1$23OEoGVk") * * - chama a função crypt(senhaFornecida, "$1$23OEoGVk") e verifica se o resultado * bate com $1$23OEoGVk$4jcc8phmHcGv.dpNkBGtu0 Bateu? Senha confere. **/ int main() { /* Na hora de sortear os caracteres de salt number, apenas os cars válidos serão usados */ char saltValidos[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuwxyz0123456789./"; char saltValidosTam = strlen(saltValidos); char senhaTextoClaro[30]; char *senhaHash; char salt[15]; char spos, i; /* Disparando uma semente de números randômicos */ srand(time(NULL)); printf("Digite uma senha:\n"); scanf("%30s", senhaTextoClaro); /* O Unix historicamente baseia o seu HASH no método DES, onde o mesmo é convertido para atuar * como hash. No DES o salt number é composto por DOIS caracteres. * (detalhes avançados de como é composto o hash DES e também o MD5 estão no artigo já citado * e em um email técnico meu que se encontra publicado em http://gravatai.ulbra.tche.br/~elgio/senhas.html * * 1) Gerando o hash DES: **/ /* Sorteando aleatoriamente um caractere do salt * técnica usada: sortei-se um inteiro entre 0 e saltValidosTam (quantidade de cars no vetor * saltValidos) este inteiro será o índice do vetor de cars */ spos = random() % saltValidosTam; salt[0] = saltValidos[spos]; srand(random()); // regerando a semente, para evitar vícios da randomicidade /* Sorteando aleatoriamente outro caractere do salt */ spos = random() % saltValidosTam; salt[1] = saltValidos[spos]; salt[2] = 0; // fechando a string printf("Acabei escolhendo %s como salt number para o DES\n", salt); senhaHash = (char *) crypt(senhaTextoClaro, salt); printf("Hash Unix DES da senha = %s\n", senhaHash); printf("Um Unix antigo armazenaria o hash %s para este usuario. ", senhaHash); printf("Observe que as duas primeiras letras do hash sao o salt escolhido\n"); /* Usar o hash DES para senhas tem sérios problemas, pois na verdade não é necessário testar 2^56 * para quebrar. Isto porque neste sistema antigo, uma senha tinha no máximo 8 caracteres, ou seja * 56 bits (pois o último bit de cada car é descartado), que eram usado como bloco de entrada. * Porém como o usuário só pode digitar letras, números e símbolos, o número de tentativas é bem * menos do que isto. Seria impossivel, por exemplo, a senha ser totalmente preenchida com bits 0! * * * 2) Gerando o hash MD5: * O crypt nunca foi preparado para lidar com MD5. Um paleativo foi colocado na lib: se o salt * number for de DOIS caracteres, é um hash DES. Se o salt number COMEÇAR com $1$, entao é MD5. * Assim mantém-se a compatibilidade. (outras versões de hash foram gradativamente introduzidas, * como o SHA1) * * Preciso passar para a função crypt, portanto, $1$<salt escolhido> para usar MD5 * **/ /* Sorteando aleatoriamente cars do salt */ salt[0] = '$'; salt[1] = '1'; salt[2] = '$'; for (i = 0; i < 8; i++) { spos = random() % saltValidosTam; salt[i + 3] = saltValidos[spos]; salt[i + 4] = 0; // fechando a string srand(random()); } printf("Acabei escolhendo %s como salt number para o MD5\n", salt); senhaHash = (char *) crypt(senhaTextoClaro, salt); printf("Hash Unix MD5 da senha = %s\n", senhaHash); printf("Um Unix novo armazenaria o hash %s para este usuario\n", senhaHash); printf("Observe que o $1$ indica ser MD5. O que vem depois ate o proximo $ eh o salt escolhido\n"); return(0); }
Esse código pode ser considerado um vírus?
[C] Criptografia por Inversão de bits
Faz um crash no Kernel do Linux
Captura de Banners dos Serviços
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Meu Fork do Plugin de Integração do CVS para o KDevelop
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Criando uma VPC na AWS via CLI
Multifuncional HP imprime mas não digitaliza
Dica básica para escrever um Artigo.
Como Exibir Imagens Aleatórias no Neofetch para Personalizar seu Terminal
Instalação Uefi com o instalador clássico do Mageia [RESOLVIDO] (2)
Melhorando a precisão de valores flutuantes em python[AJUDA] (11)
GLPI - Configuração de destinatário com conta Microsoft Exchange (0)