OneCompiler

Atividades de Programação para P2 - MD2

Gustavo Abrantes de Souza

212008160

Questão 09 - Teorema Chinês

#include <stdio.h>

// Função para calcular o inverso modular de a mod m
int inversoModular(int a, int m) {
    a = a % m;
    for (int x = 1; x < m; x++) {
        if ((a * x) % m == 1)
            return x;
    }
    return -1; // Se não existir inverso
}

// Função para resolver o sistema de congruências usando o Teorema Chinês do Resto
int teoremaChines(int n[], int a[], int k, int *N) {
    *N = 1; // Produto de todos os n_i -> N = n1.n2.n3
    for (int i = 0; i < k; i++) {
        *N *= n[i];
    }

    int X = 0;
    for (int i = 0; i < k; i++) {
        int Ni = *N / n[i]; // Calculo dos N1, N2, N3, na qual é dado por -> N/n_i
        int Xi = inversoModular(Ni, n[i]); // Inverso de Ni módulo n_i, na qual é dado por Ni.Xi ≡ 1 (mod ni)
        if (Xi == -1) {
            printf("Erro: Nao existe inverso modular para %d modulo %d\n", Ni, n[i]);
            return -1;
        }
        // Calculo do X -> X ≡ (a1.X1.N1 + a2.X2.N2 + a3.X3.N3) mod N
        X += a[i] * Ni * Xi;
    }
    return X % (*N);
}

int main() {
    int n[4], a[4];
    int k, N;

    // Leitura do número de equações (máximo 4)
    printf("Digite o numero de equacoes (ate 4): ");
    scanf("%d", &k);

    if (k > 4) {
        printf("Numero maximo de equacoes e 4.\n");
        return 1;
    }

    // Leitura dos módulos (n_i) e dos restos (a_i), seguindo o formato 

    // X ≡ a1 (mod n1)
    // X ≡ a2 (mod n2)
    // X ≡ a3 (mod n3)
    for (int i = 0; i < k; i++) {
        printf("Digite n[%d] (modulo da equacao %d): ", i + 1, i + 1);
        scanf("%d", &n[i]);
        printf("Digite a[%d] (resto da equacao %d): ", i + 1, i + 1);
        scanf("%d", &a[i]);
    }

    // Chamando a função para calcular o resultado
    int result = teoremaChines(n, a, k, &N);
    
    if (result != -1) {
        printf("A solucao do sistema de congruencias e X = %d (mod %d)\n", result, N);
    }
    return 0;
}

Questão 10 - Criptografia RSA

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

// Função para calcular o MDC (Máximo Divisor Comum)
int mdc(int a, int b) {
    if (b == 0)
        return a;
    return mdc(b, a % b);
}

// Função para calcular a função phi ou totient de Euler
int phi(int p, int q) {
    return (p - 1) * (q - 1);
}

// Função para calcular o inverso modular de e (Achar o d):
// -> e.d ≡ 1 mod phi(n)
int inversoModular(int a, int m) {
    a = a % m;
    for (int x = 1; x < m; x++) {
        if ((a * x) % m == 1)
            return x;
    }
    return -1; // Se não existir inverso
}

// Função para fazer o calculo da congruência com expoente, como em:
// m^e mod n
// c^d mod n
int exponenciacaoModular(int base, int exp, int m) {
    int resulto = 1;
    base = base % m; // definindo resto da div da base por n
    while (exp > 0) { // enquanto e (para o caso de encryptRSA) ou d (para o caso de decryptRSA) > 0
        if (exp % 2 == 1)
            resulto = (resulto * base) % m;
        exp = exp >> 1;
        base = (base * base) % m;
    }
    return resulto;
}

// Função para criptografar a mensagem
void criptografandoRSA(char *message, int e, int n) {
    printf("\n__ __ __ __ __ __ __ __ __ __ __\n");
    printf("\nMensagem criptografada: ");
    for (size_t i = 0; i < strlen(message); i++) {
        int codigo = message[i] - 'A' + 11; // Convertendo o caractere para código (A=11, B=12, etc...)
        int encrypted = exponenciacaoModular(codigo, e, n);
        printf("%d ", encrypted);
    }
    printf("\n");
    printf("__ __ __ __ __ __ __ __ __ __ __\n\n");
}

// Função para descriptografar a mensagem
void descriptografandoRSA(int *encrypted, int length, int d, int n) {
    printf("\n__-__-__-__-__-__-__-__-__-__-__\n");
    printf("\nMensagem decifrada: ");
    for (int i = 0; i < length; i++) {
        int decrypted = exponenciacaoModular(encrypted[i], d, n);
        printf("%c", (decrypted - 11) + 'A'); // Convertendo o cod de volta para caractere
    }
    printf("\n");
    printf("__-__-__-__-__-__-__-__-__-__-__\n");
}

int main() {
    int p, q, e, n, d, totiente;

    printf("Digite os primos p e q:\n");
    scanf("%d %d", &p, &q);

    n = p * q; // calculo do n
    totiente = phi(p, q); // calculo do phi
    printf("--------------------\n");
    printf("Valor de n: %d\n", n);
    printf("Valor de phi(%d): %d\n", n, totiente);
    printf("--------------------\n");

    // Entrada de "e"
    printf("Digite o valor de 'e' (1 < e < %d, coprimo com %d): ", totiente, totiente);
    scanf("%d", &e);
    if (mdc(e, phi(p,q)) != 1) { // verificando se os numeros "e" e "phi" são coprimos
        printf("Erro: %d nao e coprimo com %d.\n", e,totiente);
        return 1;
    }

    // Calculando d (inverso modular de e mod phi)
    d = inversoModular(e, totiente);
    if (d == -1) {
        printf("Erro: Nao foi possivel calcular o inverso modular.\n");
        return 1;
    }
    printf("Valor de d: %d\n", d);

    // Entrada da mensagem
    char message[100];
    printf("Digite a mensagem a ser criptografada (LETRAS MAIUSCULAS TEACHER): ");
    scanf("%s", message);

    // Criptografando a mensagem
    criptografandoRSA(message, e, n);

    // Exemplo de mensagem criptografada (entrada para descriptografia)
    int menssagemCriptografada[100], numLetras;
    printf("\nDigite o numero de letras criptografadas: "); // ex: se for AMOR a mensagem -> 4 letras
    scanf("%d", &numLetras);
    // Exemplo de entrada para ajudar professora -> 13 16 29 16
    printf("Digite o respectivo numero das letras criptografadas (COM ESPACO ENTRE UMA E OUTRA, ASSIM COMO FOI APRESENTADO ACIMA EM 'MENSAGEM CRIPTOGRAFADA'): ");
    for (int i = 0; i < numLetras; i++) {
        scanf("%d", &menssagemCriptografada[i]);
    }

    // Descriptografando a mensagem
    descriptografandoRSA(menssagemCriptografada, numLetras, d, n);

    return 0;
}

Questão 11 - Validador de CPF e ISBN usando congruência

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

// Função para calcular os dígitos verificadores do CPF
void calcularCPF(char cpf[]) {
    int soma = 0, peso = 10, i;

    // Calculando o primeiro dígito verificador
    for (i = 0; i < 9; i++) {
        soma += (cpf[i] - '0') * peso;
        peso--;
    }
    int digito1 = (soma * 10) % 11;
    if (digito1 == 10) digito1 = 0;

    // Calculando o segundo dígito verificador
    soma = 0;
    peso = 11;
    for (i = 0; i < 9; i++) {
        soma += (cpf[i] - '0') * peso;
        peso--;
    }
    soma += digito1 * 2;
    int digito2 = (soma * 10) % 11;
    if (digito2 == 10) digito2 = 0;

    // Dígitos verificadores calculados
    printf("-----------------------------------------------\n");
    printf("Primeiro digito verificador calculado: %d\n", digito1);
    printf("Segundo digito verificador calculado: %d\n", digito2);
    printf("-----------------------------------------------\n");

    // Comparando com os dígitos fornecidos
    if (digito1 == (cpf[9] - '0') && digito2 == (cpf[10] - '0')) {
        printf("CPF valido!\n");
    } else {
        printf("CPF invalido!\n");
    }
}

// Função para calcular a validade do ISBN-10
void calcularISBN(char isbn[]) {
    int soma = 0;

    // Calculando a soma ponderada
    for (int i = 0; i < 9; i++) {
        soma += (isbn[i] - '0') * (i + 1);
    }
    int checksum = soma % 11;

    // Exibindo o dígito verificador calculado
    printf("Digito verificador calculado: ");
    if (checksum == 10) {
        printf("X\n");
    } else {
        printf("%d\n", checksum);
    }

    // Verificando validade
    char ultimo = isbn[9];
    if (ultimo == 'X') {
        if (checksum == 10) {
            printf("ISBN valido!\n");
        } else {
            printf("ISBN invalido!\n");
        }
    } else {
        if (checksum == (ultimo - '0')) {
            printf("ISBN valido!\n");
        } else {
            printf("ISBN invalido!\n");
        }
    }
}

int main() {
    char cpf[12], isbn[11];

    // Entrada do CPF
    printf("Digite o CPF (apenas numeros, 11 digitos): ");
    scanf("%s", cpf);
    if (strlen(cpf) != 11) {
        printf("Erro: CPF deve ter 11 digitos.\n");
        return 1;
    }
    calcularCPF(cpf);

    // Entrada do ISBN
    printf("\nDigite o ISBN-10 (apenas numeros, 10 digitos): ");
    scanf("%s", isbn);
    if (strlen(isbn) != 10) {
        printf("Erro: ISBN-10 deve ter 10 digitos.\n");
        return 1;
    }
    calcularISBN(isbn);

    return 0;
}