Tarefa da Prova 2


FAVOR EXECUTAR NO SITE <onlinegdb.com/online_c_compiler>, pois o onecompiler não está rodando

// --------QUESTAO 01 ---------- TEOREMA CHINES DO RESTO

#include <stdio.h>

// Função para calcular o máximo divisor comum (MDC) usando o algoritmo de Euclides
int mdc(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}

// Função para calcular o inverso modular de 'a' módulo 'm' usando o algoritmo de Euclides estendido
int inverso_modular(int a, int m) {
int m0 = m, t, q;
int x0 = 0, x1 = 1;

if (m == 1)
    return 0;

while (a > 1) {
    q = a / m;
    t = m;
    m = a % m;
    a = t;
    t = x0;
    x0 = x1 - q * x0;
    x1 = t;
}

if (x1 < 0)
    x1 += m0;

return x1;

}

// Função principal para resolver o sistema de congruências
int teorema_chines_do_resto(int num[], int rem[], int k) {
int prod = 1;
int result = 0;

// Calcula o produto de todos os módulos
for (int i = 0; i < k; i++)
    prod *= num[i];

// Aplica o Teorema Chinês do Resto
for (int i = 0; i < k; i++) {
    int pp = prod / num[i];
    result += rem[i] * inverso_modular(pp, num[i]) * pp;
}

return result % prod;

}

int main() {
int num[4], rem[4], k;

printf("Digite o número de equações a serem comparadas (até 4): ");
scanf("%d", &k);

for (int i = 0; i < k; i++) {
    printf("Digite o mod e o resto da equação %d (separados por espaço): ", i + 1);
    scanf("%d %d", &num[i], &rem[i]);
}

// Verifica se os módulos são coprimos dois a dois
for (int i = 0; i < k; i++) {
    for (int j = i + 1; j < k; j++) {
        if (mdc(num[i], num[j]) != 1) {
            printf("Os módulos não são coprimos entre si. O Teorema Chinês do Resto não é aplicável.\n");
            return 1;
        }
    }
}

int x = teorema_chines_do_resto(num, rem, k);
printf("A solução é x = %d\n Número de ocorrências até que todos coincidam", x);
return 0;

}

// -----------------------------------------------

// --------QUESTAO 02 ---------- CRIPTOGRAFIA RSA

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

// Função para calcular o máximo divisor comum (MDC) usando o algoritmo de Euclides
int mdc(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}

// Função para calcular o inverso modular de 'a' módulo 'm' usando o algoritmo de Euclides estendido
int inverso_modular(int a, int m) {
int m0 = m, t, q;
int x0 = 0, x1 = 1;

if (m == 1)
    return 0;

while (a > 1) {
    q = a / m;
    t = m;
    m = a % m;
    a = t;
    t = x0;
    x0 = x1 - q * x0;
    x1 = t;
}

if (x1 < 0)
    x1 += m0;

return x1;

}

// Função para calcular (base^exp) % mod de forma eficiente
long long potencia_modular(long long base, long long exp, long long mod) {
long long resultado = 1;
base = base % mod;
while (exp > 0) {
if (exp % 2 == 1)
resultado = (resultado * base) % mod;
exp = exp >> 1;
base = (base * base) % mod;
}
return resultado;
}

// Função para criptografar uma mensagem
void criptografar(char* mensagem, long long e, long long n) {
printf("Mensagem criptografada: ");
for (int i = 0; i < strlen(mensagem); i++) {
long long m = mensagem[i] - 'A' + 11; // Pré-código: A = 11, B = 12, ..., Z = 36
long long c = potencia_modular(m, e, n);
printf("%lld ", c);
}
printf("\n");
}

// Função para descriptografar uma mensagem
void descriptografar(long long* criptograma, int tamanho, long long d, long long n) {
printf("Mensagem descriptografada (tentativa): ");
for (int i = 0; i < tamanho; i++) {
long long c = criptograma[i];
long long m = potencia_modular(c, d, n);
char caractere = (char)(m - 11 + 'A'); // Inverso do pré-código
if (m >= 11 && m <= 36) { // Verifica se o caractere está no intervalo esperado
printf("%c", caractere);
} else {
printf("?"); // Caractere inválido
}
}
printf("\n");
}

int main() {
long long p, q, n, phi, e, d;
char mensagem[100];

// Entrada para gerar as chaves
printf("Digite dois números primos separados por espaço (p e q): ");
scanf("%lld %lld", &p, &q);

n = p * q;
phi = (p - 1) * (q - 1);

printf("Digite o valor de e (coprimo com %lld): ", phi);
scanf("%lld", &e);

d = inverso_modular(e, phi);

printf("Chave pública: (e = %lld, n = %lld)\n", e, n);
printf("Chave privada: (d = %lld, n = %lld)\n", d, n);

// Entrada para criptografia
printf("Digite uma mensagem (apenas letras maiúsculas): ");
scanf("%s", mensagem);

criptografar(mensagem, e, n);

// Entrada para descriptografia
printf("Digite o tamanho da mensagem criptografada(quantos blocos de números há): ");
int tamanho;
scanf("%d", &tamanho);

long long criptograma[tamanho];
printf("Digite os números criptografados: ");
for (int i = 0; i < tamanho; i++) {
    scanf("%lld", &criptograma[i]);
}

// Solicitar a chave privada antes da descriptografia
long long d_usuario, n_usuario;
printf("Digite a chave privada e n (d e n): ");
scanf("%lld %lld", &d_usuario, &n_usuario);

// Realizar tentativa de descriptografia
descriptografar(criptograma, tamanho, d_usuario, n_usuario);

// Informar se a chave estava correta ou não
if (d_usuario == d && n_usuario == n) {
    printf("Chave correta! A mensagem foi descriptografada com sucesso.\n");
} else {
    printf("Chave privada incorreta. A mensagem descriptografada pode estar errada.\n");
}

return 0;

}

// -----------------------------------------------

// --------QUESTAO 03 ---------- CPF E ISNB

#include <stdio.h>
#include <string.h>
#include <ctype.h>

// Função para validar CPF e retornar os dígitos verificadores calculados
int validar_cpf(int cpf[], int *digito1_calculado, int *digito2_calculado) {
int soma1 = 0, soma2 = 0;

for (int i = 0; i < 9; i++) {
    soma1 += cpf[i] * (10 - i);
    soma2 += cpf[i] * (11 - i);
}

*digito1_calculado = (soma1 * 10) % 11;
if (*digito1_calculado == 10) *digito1_calculado = 0;

soma2 += (*digito1_calculado) * 2;
*digito2_calculado = (soma2 * 10) % 11;
if (*digito2_calculado == 10) *digito2_calculado = 0;

return *digito1_calculado == cpf[9] && *digito2_calculado == cpf[10];

}

// Função para validar ISBN e retornar o dígito verificador calculado
int validar_isbn(int isbn[], int *digito_calculado) {
int soma = 0;

for (int i = 0; i < 9; i++) {
    soma += isbn[i] * (10 - i);
}

*digito_calculado = 11 - (soma % 11);
if (*digito_calculado == 10) *digito_calculado = 'X';
else if (*digito_calculado == 11) *digito_calculado = 0;

return *digito_calculado == isbn[9];

}

int main() {
int escolha;
printf("O que você deseja verificar?\n");
printf("1 - CPF\n");
printf("2 - ISBN\n");
printf("Digite sua escolha (1 ou 2): ");
scanf("%d", &escolha);

if (escolha == 1) {
    // Validação do CPF
    char cpf_input[12];
    int cpf[11], digito1_calculado, digito2_calculado;

    printf("Digite os 11 dígitos do CPF (apenas números): ");
    scanf("%s", cpf_input);

    // Verificar se o CPF tem exatamente 11 dígitos
    if (strlen(cpf_input) != 11) {
        printf("Erro: O CPF deve ter exatamente 11 dígitos.\n");
        return 1;
    }

    // Converter a string para um array de inteiros
    for (int i = 0; i < 11; i++) {
        if (!isdigit(cpf_input[i])) {
            printf("Erro: O CPF deve conter apenas números.\n");
            return 1;
        }
        cpf[i] = cpf_input[i] - '0';
    }

    if (validar_cpf(cpf, &digito1_calculado, &digito2_calculado))
        printf("CPF válido.\n");
    else {
        printf("CPF inválido.\n");
        printf("Os dígitos verificadores corretos seriam: %d e %d.\n", digito1_calculado, digito2_calculado);
    }
} else if (escolha == 2) {
    // Validação do ISBN
    char isbn_input[11];
    int isbn[10], digito_isbn_calculado;

    printf("Digite os 10 dígitos do ISBN (último dígito pode ser 'X'): ");
    scanf("%s", isbn_input);

    // Verificar se o ISBN tem exatamente 10 caracteres
    if (strlen(isbn_input) != 10) {
        printf("Erro: O ISBN deve ter exatamente 10 caracteres.\n");
        return 1;
    }

    // Converter a string para um array de inteiros
    for (int i = 0; i < 9; i++) {
        if (!isdigit(isbn_input[i])) {
            printf("Erro: O ISBN deve conter apenas números nos primeiros 9 dígitos.\n");
            return 1;
        }
        isbn[i] = isbn_input[i] - '0';
    }

    // Tratar o último dígito do ISBN (pode ser número ou 'X')
    if (isbn_input[9] == 'X' || isbn_input[9] == 'x') {
        isbn[9] = 'X';
    } else if (isdigit(isbn_input[9])) {
        isbn[9] = isbn_input[9] - '0';
    } else {
        printf("Erro: O último dígito do ISBN deve ser um número ou 'X'.\n");
        return 1;
    }

    if (validar_isbn(isbn, &digito_isbn_calculado)) {
        printf("ISBN válido.\n");
    } else {
        printf("ISBN inválido.\n");
        if (digito_isbn_calculado == 'X')
            printf("O dígito verificador correto seria: X.\n");
        else
            printf("O dígito verificador correto seria: %d.\n", digito_isbn_calculado);
    }
} else {
    printf("Escolha inválida. Digite 1 para CPF ou 2 para ISBN.\n");
}

return 0;

}