All pastes #784421 Raw Edit

criptografia RSA

public c v1 · immutable
·published 2007-11-19 18:12 UTC
rendered paste body
#include <stdio.h>#include <stdlib.h>#include <time.h>#include <string.h>#include <arquivo.h>#include <dir.h>/*Biblioteca que contém a função para criar diretórios*/#include <gmp.h>/*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âmtrosoutras duas contantes (_str e _n) indicadoras de tipos String e inteirose se utiliza da função memset para setar o caracter '\0' nas posições dememó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 docompilador, que muitas vezes, ja trás a String com valores diversos setados.*//*A metodologia utilizada neste sistema está descrita no sitehttp://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 nacriação das chaves.A função rand devolvendo o mod do numero randômico gerado por 100para 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çãoda mensagem. Com o auxílio das funções da header arquivo.h é feita a conversãotanto 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 utilizadasno processo de encriptação e desencriptação. Para tal, ela utiliza os númerosprimos gerados pela função geraKey().Esta função faz grande uso das funções da Biblioteca GMP que é especializada emtrabalhos 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<strlen(mensagem); j++)    {        aux_d = conv_texto(mensagem[j]);        /*        A função conv_texto converte um caráter em um valor numérico        pré-estabelecido. O valro retornado vai para a variável aux_d.        */        /***********        Início da encriptação do número obtido        TEXTO CRIPTOGRAFADO = (TEXTO ORIGINAL ^ E) mod N        */        mpz_set_ui(msg, aux_d);        /*        Convertendo o valor de unsigned long int para mpz_t        */        mpz_pow_ui(res, msg, e);        mpz_mod(msgcrip, res, n);        /*Fim do processo de encriptação        *************/                /**********        Inicio do processo de geraçãode String para gravação em arquivo        */        aux_d = mpz_get_ui(msgcrip);        /*Convertendo um número mpz_t para unsigned long int*/        itoa(aux_d, mensagem_aux, 10);        /*Convertendo um número inteiro para uma String*/        strcat(mensagem_encrip, mensagem_aux);        strcat(mensagem_encrip, "+");        /*Gravando a String obtida em outra (mensagem_encrip) que, a cada ciclo, receberá o         no número gerado separado pelo sinal + que facilitará na hora de desencriptar        o número gerado*/    }    /*Fim do laço        *************/                 mkdir("C:\\Cryptos");         /*Função para criar a Pasta onde serão salvos os arquivos.*/         char arquivo[15];         strcpy(arquivo, "C:\\Cryptos\\msg_orig.txt");                  escrita(mensagem, arquivo);         /*A função escrita passa como parâmetro a mensagem e o arquivo que será gerado         na gravação da mensagem criptografada. Aqui se salva a mensagem original*/                  strcpy(arquivo, "C:\\Cryptos\\msg_crip.txt");         escrita(mensagem_encrip, arquivo);         /*Aqui é salva a mensagem encriptada*/                  printf("\n\nMensagem Encriptada com sucesso. A mensagem foi salva em C:/Cryptos.\n\n");                                 void decript(char arquivo[], unsigned long int n, unsigned long int d);         aux_d = mpz_get_ui(n);         /*Convertendo o valor da variável n (mpz_t) para unsigned long int*/                  decript(arquivo, aux_d, d);         /*Já chamando a função decript, passando como parâmetros uma String com         o local e arquivo onde esta o arquivo a ser decriptado e a chave privada         composta pela formação das variáveis N (saldo em aux_d) e d*/                 /*De acordo com a documentação da biblioteca GMP, é recomendado que a        cada ciclo finalizado, as variáveis desta biblioteca sejam limpas. Isso        ajuda na performance, pois estas variáveis armazenam números muito        grandes. A função mpz_clear é responsável por esta limpeza.*/        mpz_clear(n);        mpz_clear(aux);        mpz_clear(z);        mpz_clear(msg);        mpz_clear(msgcrip);        mpz_clear(res);   }void decript(char arquivo[], unsigned long int n, unsigned long int d){     /*A função decript faz a leitura e decriptação do arquivo passado na     String arquivo[]. Para tal, faz uso da chave privada do usuário composto     pelos valores das variáveis n e d, passadas aqui como parâmetro.*/          ler(&arquivo);     /*A função ler recebe como parâmetro a localização do arquivo e devolve     na mesma variável que passa o parâmetro o conteúdo do arquivo, no nosso     caso, e mensagem encriptada.*/          int i=0, j=0, k=0, p;      unsigned long int num;     char arquivo_g[25];/*Armazenará o local onde será salvo o arquivo decifrado*/     char aux[10];     char mensagem[1024];     char mensagem_dec[1024];     char ch;     char ch_dec;          /*Variáveis inteiras da biblioteca GMP*/     mpz_t msgcrip;     mpz_t res;     mpz_t msg;     mpz_t aux_m;          /*Inicialização das variáveis inteiras da biblioteca GMP*/     mpz_init(msgcrip);     mpz_init(res);     mpz_init(msg);     mpz_init(aux_m);          /*Limpando préviamente as Strings para evitar problemas com conteúdo     indesejado no futuro*/     LIMPA_STRING(mensagem, strlen(mensagem));     LIMPA_STRING(aux, strlen(aux));     LIMPA_STRING(mensagem_dec, strlen(mensagem_dec));          strcpy(mensagem, arquivo);     /*Passando o texto encriptado para a string mensagem*/          p = strlen(arquivo);     /*Obtendo o tamanho da String*/     /**********     LAÇO PARA EXTRAIR E DESENCRIPTAR OS NÚMEROS DO TEXTO*/     do     {          /*          Este laço irá percorrer toda a string mensagem (que contém números          separado com um sinal de "+"). Durante o laço, cada vez que se chegar          a um caracter "+", o laço interpretará como um número inteiro isolado,          procedendo à sua desencriptação, chegando ao número verdadeiro e          convertendo esse número para sua letra correspondente.          */          if(ch!='+')          {              /*              Enquanto o conteúdo da String ch (que recebe mais abaixo cada              string de numero da string mensagem) for diferente de "+", a string              auxiliar aux recebe este conteúdo (que por enquanto, é um numero              em forma de String). Quando chegar ao caracter "+", teremos um              numero formado, pronto para ser decriptado              */                     aux[j] = mensagem[k];                            j++;              /*Contador da string aux*/              k++;              /*Contador da string mensagem*/          }else          {              /*              Quando chega aqui (no caso, quando ch recebe o "+"), já temos um              numero inteiro formado em forma de string na variável aux. Esta              string será convertida para um numero inteiro para que se possa              proceder com os calculos.              Para evitar problemas com imprecisão de cálculos, todo o              procedimento de cálculo acontece dentro de variáveis inteiras da              biblioteca GMP.              */               j=0;               /*Reiniciamos o contador para a variável aux, que a partir da               próxima rodada, receberá um novo número. Mais a frente, a própria               variável aux será zerada.*/                              k++;               num = atoi(aux);               /*Convertendo o valor da string aux para um numero inteiro*/               /**********               Incio do processo de desencriptação da mensagem*/               /*               Metodologia:               TEXTO ORIGINAL = (TEXTO CRIPTOGRAFADO ^ D) mod N               */               mpz_set_ui(msgcrip, num);               /*Setando o valor unsigned long int de num para uma variável               inteira mpz_t, para qeu todo o cálculo envolvido na decriptação               ocorra dentro do ambiente da GMP*/               mpz_pow_ui(res, msgcrip, d);               /*(TEXTO CRIPTOGRAFADO ^ D). res é uma variável auxiliar*/               mpz_mod_ui(msg, res, n);               /*res MOD N. msg recebe o resultado, que é o próprio numero               agora decriptado*/               num = mpz_get_ui(msg);               /*Converte novamente para um valor unsigned long int*/               ch_dec = un_conv_texto(num);               /*A função un_conv_texto recebe o numero agora decriptado e               com esse numero traz de volta o carácter correspondente a este               numero*/               mensagem_dec[i] = ch_dec;               /*A cada rodada de decriptação a string mensagem_dec recebe o               carácter encontrado, que formará o texto a ser descoberto*/               i++;               LIMPA_STRING(aux, strlen(aux));               /*Aqui limpamos o conteúdo da variável aux que a partir da               próxima rodada, receberá um novo numero a ser decriptado*/                              /*Fim do processo               *********/          }          ch = mensagem[k];     }     while (k<p-1);     /*      FIM DO LAÇO     *********/     strcpy(arquivo_g, "C:\\Cryptos\\texto_decrip.txt");     escrita(mensagem_dec, arquivo_g);     /*Gravamos o conteúdo decriptado salvo na string mensagem_dec em um arquivo     na pasta C:/Cryptos*/          /*De acordo com a documentação da biblioteca GMP, é recomendado que a    cada ciclo finalizado, as variáveis desta biblioteca sejam limpas. Isso    ajuda na performance, pois estas variáveis armazenam números muito    grandes. A função mpz_clear é responsável por esta limpeza.*/     mpz_clear(msgcrip);     mpz_clear(res);     mpz_clear(msg);     mpz_clear(aux_m);}