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;
}