#include #include #include #include #include #include /*Biblioteca que contém a função para criar diretórios*/ #include /*Biblioteca para cálculos de números grandes*/ #define LIMPA_STRING( _str, _n ) memset( _str, '\0', _n ) /*Aqui definimos uma função como contante. Esta função recebe como parâmtros outras duas contantes (_str e _n) indicadoras de tipos String e inteiros e se utiliza da função memset para setar o caracter '\0' nas posições de memória da String. Esta função serve para apagar o conteúdo de uma String. Esta função é utilizada em razão da ineficiência do controle de Buffer do compilador, que muitas vezes, ja trás a String com valores diversos setados.*/ /* A metodologia utilizada neste sistema está descrita no site http://www.dicas-l.com.br/dicas-l/20070611.php. */ bool primo (int p){ /* Esta função verifica se os números que passam por ela são primos. Caso sejam, retorna true. Caso não, retorna false. */ int i, div=0; bool pri = false; for (i=1; i<=p; i++) { if (p%i == 0) div++; } if (div == 2) pri = true; return (pri); } void geraKeys(int *primoP, int *primoQ, int *primoD){ /* Apesar do nome, esta funçãonão gera as chaves criptográficas. Esta função gera os 3 números primos que serão utilizados na criação das chaves. A função rand devolvendo o mod do numero randômico gerado por 100 para que não gere números primos muito grandes e conseqüentemente, termos falhas de imprecisão de cálculo. Para o nosso caso, os números gerados não terão mais que 2 dígitos. */ printf("Gerando chaves. Aguarde...\n"); //Atribui um número primo ao P do { *primoP = 0; srand(time(NULL)); *primoP = (rand()%100); } while(!primo(*primoP)); //Atribui um número primo ao Q do { *primoQ = 0; srand(time(NULL)); *primoQ = (rand()%100); } while((!primo(*primoQ)) || (*primoQ == *primoP)); //Atribui um número primo ao D do { *primoD = 0; srand(time(NULL)); *primoD = (rand()%100); } while((!primo(*primoD)) || (*primoD == *primoP) || (*primoD == *primoQ)); printf("\nChaves Geradas com Sucesso."); } void encript(int primoP, int primoQ, int primoD) { /* A Função Encript é responsável por todo o processo de encriptação da mensagem. Com o auxílio das funções da header arquivo.h é feita a conversão tanto de número para letra quanto de letra para número. Esta função é quem de fato gera as chaves públicas e privadas que serão utilizadas no processo de encriptação e desencriptação. Para tal, ela utiliza os números primos gerados pela função geraKey(). Esta função faz grande uso das funções da Biblioteca GMP que é especializada em trabalhos com números grandes. */ unsigned long int p, q, d, e, aux_d, i, j, k, w; /* Este tipo de inteiro é necessário por oferecer maior capacidade quanto ao tamanho dos números que comporta. */ char mensagem [512]; char mensagem_encrip [1024]; char mensagem_aux [15]; /* Estas Strings serão utilizadas no processo de transformação das mensagem para número e vice-versa. */ /*Declaração de variáveis inteiras da biblioteca GMP.*/ mpz_t n, z, msg, msgcrip, res, aux; /*Inicialização das variáveis da biblioteca GMP. A biblioteca GMP requer que suas variáveis sejam inicializadas por meio de uma função específica.*/ mpz_init(n); mpz_init(aux); mpz_init(z); mpz_init(msg); mpz_init(msgcrip); mpz_init(res); p = primoP; q = primoQ; d = primoD; /*D junto com o N é utilizado como chave privada. Este é um número que é tido como primo em relação à Z, que será obtido mais a frente*/ mpz_set_ui(n, p*q); // N junto com E, é utilizado como chave pública /* N = P * Q O método mpz_set_ui atribui a uma variável do tipo mpz_r um valor do tipo unsigned long int. No nosso caso, já fazemos a atribuição do resultado de uma multiplicação de inteiros. */ mpz_set_ui(z, (p-1)*(q-1)); /* * Z = (P - 1) * (Q - 1) Idem variável anterior. O z será uma variavel auxiliar no processo de obtenção do número. */ e = 0; /* O valor da variável E será utilizado na geração da chave pública. */ aux_d = 1; /* Esta variável é utilizada apenas para ajudar no processo de comparação mais à frente*/ /*Variável long int para auxiliar na comparação com números GMP. A GMP não faz comparações ou operações diretas com números inteiros*/ //Início do laço para encontrar o valor da variável e. do { /* (E * D) mod Z = 1 O E encontrado aqui será utilizado na chave pública, */ e++; mpz_set_ui(aux, e*d); mpz_mod(aux, aux, z); /* A função mpz_mod retorna a uma variável mpz_t o módulo, ou resto da divisão de dois números também do tipo mpz_t. */ } while ((mpz_cmp_ui(aux, aux_d))!=0); //Fim do laço printf("\nAnote suas chaves:: \n"); gmp_printf("\nChave publica: E: %d N: %Zd", e, n); gmp_printf("\nChave privada: D: %d N: %Zd", d, n); printf("\n\nDigite sua mensagem (Tamanho maximo: 511 caracteres).\n"); gets(mensagem); /* A String mensagem guardará a mensagem que usuário ira criptografar */ /* Metodologia de criptografia RSA: TEXTO CRIPTOGRAFADO = (TEXTO ORIGINAL ^ E) mod N TEXTO ORIGINAL = (TEXTO CRIPTOGRAFADO ^ D) mod N */ LIMPA_STRING(mensagem_encrip, strlen(mensagem_encrip)); /*Limpando préviamente o conteúdo da string mensagem_encrip para evitar problemas com conteúdo indesejado daqui pra frente.*/ /********** Início Laço para extrair e encriptar a mensagem letra por letra */ for (j = 0; j