OneCompiler

Atividade_2


/*
Para facilitar o o uso do algoritmo criei uma interface com switch case:
caso tente roda-lo pela propria plataforma, é nescessário colococar o numero da opção que deseja testar e logo abaixo o caso
a ser verificado
"
DIGITE PARA:
 1: CPF
 2: ISBN
 3: CRIPTOGRAFIA RSA
 4: TEOREMA CHINES
 0: SAIR
"
EXEMPLO:
1
xxxxxxxxx
E o algoritmo irá retornar, no caso, o cpf com os dois digitos verificadores

*/

#include <stdio.h>
#define mod(a, b) (((a) % (b) + (b)) % (b)) // Função para calcular o módulo sempre positivo

// Função para calcular o CPF
void calcula_cpf()
{
    int soma = 0;
    int soma2 = 0;
    char cpf[10];

    // Entrada dos primeiros 9 dígitos do CPF
    printf("Digite os 9 primeiros digitos do CPF:\n");
    scanf("%s", cpf);

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

    // Calcula o segundo dígito verificador
    for (int i = 0; i < 9; i++)
    {
        int digito2 = cpf[i] - '0';
        soma2 += (i * digito2);
    }
    soma2 += (D1 * 9);
    int D2 = soma2 % 11;
    if (D2 == 10)
        D2 = 0;

    // Exibe o CPF completo
    printf("CPF com os digitos verificadores:\n");
    printf("%s-%d%d\n", cpf, D1, D2);
}

// Função para calcular o ISBN
void calcula_isbn()
{
    int soma = 0;
    char isbn[10];

    printf("Digite o codigo ISBN:\n");
    scanf("%s", isbn);

    // Cálculo do somatório
    for (int i = 0; i < 9; i++)
    {
        int digito = isbn[i] - '0';
        soma += digito * (10 - i);
    }
    int resto = soma % 11;
    int controle = (11 - resto) % 11;

    // Exibe o ISBN completo
    if (controle == 10)
    {
        printf("%sX\n", isbn);
    }
    else
    {
        printf("%s%d\n", isbn, controle);
    }
}

// Função para calcular o MDC (Máximo Divisor Comum)
int calculaMDC(int x, int y)
{
    if (y == 0)
        return x;
    return calculaMDC(y, mod(x, y));
}

// Função para calcular o inverso modular
int calculaInversoModular(int chave, int totiente)
{
    for (int i = 1; i < totiente; i++)
    {
        if (mod((chave * i), totiente) == 1)
        {
            return i;
        }
    }
    return -1; // Caso não exista inverso modular
}

// Função para calcular exponenciação modular
int calculaExponenciacaoModular(int valorBase, int exp, int modAtual)
{
    int resultadoFinal = 1;
    valorBase %= modAtual;
    while (exp > 0)
    {
        if (exp % 2 == 1)
        {
            resultadoFinal = (resultadoFinal * valorBase) % modAtual;
        }
        valorBase = (valorBase * valorBase) % modAtual;
        exp /= 2;
    }
    return resultadoFinal;
}

// Função para resolver congruências no formato kx = b (mod n)
int resolveCongruencia(int k, int b, int n, int *x)
{
    int d = calculaMDC(k, n);
    if (mod(b, d) != 0)
        return 0; // Sem solução

    int k_inv = calculaInversoModular(k / d, n / d);
    if (k_inv == -1)
        return 0;

    *x = mod((b / d) * k_inv, n / d);
    return 1;
}

int main()
{
    printf("DIGITE PARA:\n 1: CPF\n 2: ISBN\n 3: CRIPTOGRAFIA RSA\n 4: TEOREMA CHINES\n 0: SAIR\n");
    int control;
    scanf("%d", &control);
    while (control != 0)
    {
        if (control == 1)
        {
            calcula_cpf();
        }
        else if (control == 2)
        {
            calcula_isbn();
        }
        if (control == 3)
        {
            int p, q, e, tamanhoBloco;

            // Entrada dos números primos p e q, e da chave pública e
            printf("Digite dois números primos (p e q):\n");
            scanf("%d %d", &p, &q);
            printf("Digite o valor de e (chave pública):\n");
            scanf("%d", &e);
            printf("Digite o tamanho do bloco:\n");
            scanf("%d", &tamanhoBloco);

            // Cálculo de n e z
            int n = p * q;
            int z = (p - 1) * (q - 1);

            // Validação se e é coprimo com z
            if (calculaMDC(e, z) != 1)
            {
                printf("Erro: O valor de e não é coprimo com z.\n");
                return 1;
            }

            int d = calculaInversoModular(e, z);

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

            getchar();
            char mensagem[100];
            printf("Insira a mensagem a ser criptografada:\n");
            fgets(mensagem, sizeof(mensagem), stdin);

            // Conversão da mensagem em valores numéricos
            int mensagemCodificada[100];
            int tamanhoCodificado = 0;
            for (int i = 0; mensagem[i] != '\0'; i++)
            {
                char c = mensagem[i];
                int valor;

                if (c == ' ')
                    valor = 0; // Espaços representam 0
                else if (c >= 'A' && c <= 'Z')
                    valor = c - 'A' + 11;
                else if (c >= 'a' && c <= 'z')
                    valor = c - 'a' + 11;
                else
                    valor = (int)c;

                mensagemCodificada[tamanhoCodificado++] = valor;
            }

            // Exibição da mensagem codificada numericamente
            printf("Mensagem codificada numericamente:\n");
            for (int i = 0; i < tamanhoCodificado; i++)
            {
                printf("%d ", mensagemCodificada[i]);
            }
            printf("\n");

            // Criptografia em blocos
            int blocosCriptografados[100];
            int tamanhoCriptografado = 0;
            for (int i = 0; i < tamanhoCodificado; i += tamanhoBloco)
            {
                int bloco = 0;
                int multiplicador = 1;

                for (int j = 0; j < tamanhoBloco && (i + j) < tamanhoCodificado; j++)
                {
                    bloco += mensagemCodificada[i + j] * multiplicador;
                    multiplicador *= 100;
                }

                blocosCriptografados[tamanhoCriptografado++] = calculaExponenciacaoModular(bloco, e, n);
            }

            // Exibição dos blocos criptografados
            printf("Mensagem criptografada:\n");
            for (int i = 0; i < tamanhoCriptografado; i++)
            {
                printf("%d ", blocosCriptografados[i]);
            }
            printf("\n");

            // Decodificação da mensagem
            int mensagemDecodificada[100];
            int tamanhoDecodificado = 0;
            for (int i = 0; i < tamanhoCriptografado; i++)
            {
                int bloco = calculaExponenciacaoModular(blocosCriptografados[i], d, n);

                while (bloco > 0)
                {
                    mensagemDecodificada[tamanhoDecodificado++] = bloco % 100;
                    bloco /= 100;
                }
            }

            // Exibição da mensagem decodificada numericamente
            printf("Mensagem decodificada numericamente:\n");
            for (int i = 0; i < tamanhoDecodificado; i++)
            {
                printf("%d ", mensagemDecodificada[i]);
            }
            printf("\n");

            // Conversão da mensagem de volta para texto
            printf("Mensagem decodificada:\n");
            for (int i = 0; i < tamanhoDecodificado; i++)
            {
                int valor = mensagemDecodificada[i];
                if (valor >= 11 && valor <= 36)
                {
                    printf("%c", (char)(valor - 11 + 'A'));
                }
                else
                {
                    printf("%c", (char)valor);
                }
            }

            printf("\n");
        }
        if (control == 4)
        {
            int a[4], n[4], totalEquacoes = 0, continuar = 1;

            printf("Insira as equações no formato 'kx = b (mod n)'. Digite '0 0 0' para encerrar.\n");

            for (int i = 0; i < 4 && continuar; i++)
            {
                int k, b, ni;
                printf("Digite os valores de 'k', 'b' e 'n' para a equação %d:\n", totalEquacoes + 1);
                scanf("%d %d %d", &k, &b, &ni);

                if (k == 0 && b == 0 && ni == 0)
                {
                    continuar = 0;
                }
                else if (ni <= 0)
                {
                    printf("O valor de 'n' deve ser positivo. Tente novamente.\n");
                    i--;
                }
                else
                {
                    int x;
                    if (!resolveCongruencia(k, b, ni, &x))
                    {
                        printf("Sem solução para a equação %dx = %d (mod %d). Tente novamente.\n", k, b, ni);
                        i--;
                    }
                    else
                    {
                        a[totalEquacoes] = x;
                        n[totalEquacoes] = ni;
                        totalEquacoes++;
                    }
                }
            }

            if (totalEquacoes == 0)
            {
                printf("Nenhuma equação foi inserida.\n");
                return 0;
            }

            int N = 1;
            for (int i = 0; i < totalEquacoes; i++)
                N *= n[i];

            int resultado = 0;
            for (int i = 0; i < totalEquacoes; i++)
            {
                int Ni = N / n[i];
                int xi = calculaInversoModular(Ni, n[i]);
                resultado += a[i] * xi * Ni;
            }
            resultado = mod(resultado, N);

            printf("A solução para o sistema de congruências é: x = %dt + %d\n", N, resultado);
        }
        return 0;
    }
}