A estocasticidade (ou aleatoriedade) é um dos pilares de qualquer sistema de segurança. Em geradores de números aleatórios, quão mais aleatória e incerta é a geração dos dados, melhor a qualidade daquele gerador e mais seguro é o seu uso em sistema de criptografia ponta-a-ponta, funções de hash, geração de chaves PGP, entre outros.
Sabendo disso, você decidiu usar essa geração de números aleatórios para criar um gerador de senhas seguras. Para ser considerada segura, a sua senha deve ter 8 caracteres. Esses 8 caracteres devem ser distribuídos entre:
  • 2 números
  • 2 letras maiúsculas
  • 2 letras minúsculas
  • 2 símbolos especiais (, ; #, $, %, &)
Crie uma função em C que gera uma senha segura de 8 caracteres seguindo as regras acima. Dica: gere números aleatórios e consulte a tabela ASCII para converter de números para caracteres.

Passo 1

O enunciado pede uma função em C que gere uma senha de exatamente 8 caracteres, contendo:
  • 2 dígitos numéricos ( 0 9)
  • 2 letras maiúsculas ( A Z)
  • 2 letras minúsculas ( a z)
  • 2 símbolos especiais escolhidos entre ,, ;, #, $, %, &
O conteúdo principal envolve: gerar números aleatórios com rand(), converter esses valores para caracteres usando a tabela ASCII e embaralhar os caracteres para não virem agrupados por tipo.

Passo 2

Definir os conjuntos de caracteres permitidos e a função de sorteio. Vamos criar quatro strings constantes contendo cada categoria:
const char *digits     \(=\) "\(0123456789\)";
const char *uppers     \(=\) "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *lowers     \(=\) "abcdefghijklmnopqrstuvwxyz";
const char *symbols    \(=\) ",;#$%&";
Cada string servirá de “lookup” para selecionarmos um caractere aleatório dentro dela usando rand() e o tamanho da string.

Passo 3

Alocar um vetor de posições para armazenar a senha ( caracteres mais o terminador nulo) e, em seguida, sortear caracteres de cada categoria:
char password[9];
for (int i = 0; i < 2; i++) {
    password[i]   = digits[rand() % 10];
    password[i+2] = uppers[rand() % 26];
    password[i+4] = lowers[rand() % 26];
    password[i+6] = symbols[rand() % 6];
}
Isso preenche as posições
  • \(0,1\) com dígitos,
  • \(2,3\) com maiúsculas,
  • \(4,5\) com minúsculas,
  • \(6,7\) com símbolos.

Passo 4

Embaralhar os 8 caracteres para que os tipos fiquem distribuídos de forma aleatória. Podemos usar o algoritmo Fisher–Yates:
for (int i = 7; i > 0; i--) {
    int j = rand() % (i + 1);
    char tmp = password[i];
    password[i] = password[j];
    password[j] = tmp;
}
Em seguida, garantimos o terminador de string:
password[8] = '\0';

Passo 5

Preparar a função completa, incluindo a semente para rand(), por exemplo vinda de time(NULL), e um protótipo que retorne ou imprima a senha.

Resposta

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void generate_password(char password[9]) {
    const char *digits  = "0123456789";
    const char *uppers  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const char *lowers  = "abcdefghijklmnopqrstuvwxyz";
    const char *symbols = ",;#$%&";
    
    // Gera \(2\) de cada categoria
    for (int i = 0; i < 2; i++) {
        password[i]   = digits[rand() % 10];
        password[i+2] = uppers[rand() % 26];
        password[i+4] = lowers[rand() % 26];
        password[i+6] = symbols[rand() % 6];
    }
    // Embaralha com Fisher--Yates
    for (int i = 7; i > 0; i--) {
        int j = rand() % (i + 1);
        char tmp = password[i];
        password[i] = password[j];
        password[j] = tmp;
    }
    password[8] = '\0';
}

int main() {
    srand((unsigned)time(NULL));
    char pwd[9];
    generate_password(pwd);
    printf("Senha gerada: %s\n", pwd);
    return 0;
}

Exercícios relacionados