segunda-feira, 17 de novembro de 2014

Teorema Fundamental da Aritmética em BIGNUM

Segue implementação do Teorema Fundamental da Aritmética em BIGNUM do OpenSSL:

---------- tfa.c ----------
/* Kryptonia - Cryptography Intelligent Research.
 * http://www.securitylabs.com.br/
 *
 * Projeto Zahlen - Teorema Fundamental da Aritmetica.
 *
 * Glaudson Ocampos <glaudson@securitylabs.com.br>
 *
 * Compile com:
 *
 * $ gcc -o tfa tfa.c -lssl -lcrypto -Wall
 *
 *
 * Implementamos apenas trial division para checar novos primos.
 * Como se trata apenas de algo conceitual, nao recomendo a utilizacao
 * de numeros gigantes.
 *
 */




/*
 * Teorema Fundamental da Aritmetica declara que todos os numeros
 * inteiros maiores que 1 podem ser decompostos em um produto de numeros
 * primos.
 *
 */

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

#include <openssl/bn.h>
#include <openssl/err.h>


#define    VERSAO    "0.1"
#define    ERRO    -1

void
uso(char *progname){
    fprintf(stdout,"Projeto Zahlen - versao %s\n",VERSAO);
    fprintf(stdout,"Uso: %s <numero>\n\n",progname);
    fprintf(stdout,"Exemplo:\n\n");
    fprintf(stdout,"./%s <513>\n\n",progname);
    fflush(stdout);
}


int
main(int argc, char *argv[]){
    BIGNUM *N = NULL, *p=NULL, *dv=NULL, *rem=NULL, *a=NULL, *r=NULL, *n=NULL;
    BN_CTX *ctx = NULL;
    char *numero = NULL;

    if(argc < 2){
        uso(argv[0]);
        _exit(0);
    }

    N = BN_new();
    if(N == NULL){
        fprintf(stderr,"Erro na criacao de bignum!\n");
        fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
        fflush(stderr);
        _exit(ERRO);
    }

    fprintf(stdout,"*** Setando valor para Bignum...");
    numero = argv[1];
    if(BN_dec2bn(&N, numero) == 0){
        fprintf(stderr,"Erro em setar valor para BN!\n");
        fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
        fflush(stderr);
        _exit(ERRO);       
    }
    fprintf(stdout,"OK.\n");
    fprintf(stdout,"*** Checando se numero eh primo...");

    /* checamos se o numero eh primo, se for, a gente jah para a execucao */

    if(BN_is_prime(N, 100, NULL, NULL, NULL) == 0){
        fprintf(stdout," Numero composto.\n");
        fflush(stdout);
    } else {
        fprintf(stdout," Numero primo.\n");
        fflush(stdout);
        _exit(0);
    }

    /* dividimos N e analisamos se deixa resto */
   
    p = BN_new();
    if(p == NULL){
               fprintf(stderr,"Erro na criacao de bignum - p!\n");
               fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
               fflush(stderr);
               _exit(ERRO);

    }
   
        dv = BN_new();
        if(dv == NULL){
               fprintf(stderr,"Erro na criacao de bignum - dv!\n");
               fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
               fflush(stderr);
               _exit(ERRO);
        
        }


        rem = BN_new();
        if(rem == NULL){
               fprintf(stderr,"Erro na criacao de bignum - rem!\n");
               fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
               fflush(stderr);
               _exit(ERRO); 
               
        }


    /* comecamos a divisao com o primeiro numero primo */
           if(BN_dec2bn(&p, "2") == 0){
                fprintf(stderr,"Erro em setar valor para p!\n");
                fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
                fflush(stderr);
                _exit(ERRO);
        }
   
        a = BN_new();
        if(a == NULL){
               fprintf(stderr,"Erro na criacao de bignum - a!\n");
               fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
               fflush(stderr);
               _exit(ERRO);
       
        }

        if(BN_dec2bn(&a, "1") == 0){
                fprintf(stderr,"Erro em setar valor 1 para a!\n");
                fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
                fflush(stderr);
                _exit(ERRO);
        }


        r = BN_new(); 
        if(r == NULL){
               fprintf(stderr,"Erro na criacao de bignum - r!\n");
               fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
               fflush(stderr);
               _exit(ERRO);
               
        }

        n = BN_new();
        if(n == NULL){
               fprintf(stderr,"Erro na criacao de bignum - n!\n");
               fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
               fflush(stderr);
               _exit(ERRO);
       
        }



    ctx = BN_CTX_new();
        if(ctx == NULL){
               fprintf(stderr,"Erro na criacao de BN_ctx!\n");
               fprintf(stderr,"%s\n",ERR_error_string(ERR_get_error(),NULL));
               fflush(stderr);
               _exit(ERRO);
       
        }

    /* */

    fprintf(stdout,"*** Primos: \n");
    fflush(stdout);

    n = N;
    while(1){
         BN_div(dv,rem, n, p, ctx);
//        fprintf(stdout,"n = %s - primo = %s - dv = %s - resto =  %s\n", BN_bn2dec(n),BN_bn2dec(p),BN_bn2dec(dv),BN_bn2dec(rem));
        if(atoi(BN_bn2dec(dv)) == 1) {
            fprintf(stdout,"%s ",BN_bn2dec(p));
            fflush(stdout);
            break;
        }
        if(atoi(BN_bn2dec(rem)) == 0){
                       fprintf(stdout,"%s ",BN_bn2dec(p));
                          fflush(stdout);
        }

        if((BN_is_prime(dv, 100, NULL, ctx, NULL) == 1) && (atoi(BN_bn2dec(rem)) == 0)){
            fprintf(stdout,"%s",BN_bn2dec(dv));
            fflush(stdout);
            break;
        }
        if(atoi(BN_bn2dec(rem)) > 0){
            n = N;
            while(1){
                BN_add(r, p, a);
                p = r;
                if(BN_is_prime(p, 100, NULL, ctx, NULL) == 1){
                    break;
                }
            }
        }
        else {
            BN_add(n, dv, rem);
        }


    }

    fprintf(stdout,"\n\n");
    fflush(stdout);

    BN_free(N);
    BN_free(p);
    BN_free(rem);
    BN_free(dv);
    BN_free(a);
//    BN_free(r); // ponteiro - double free
//    BN_free(n); // ponteiro - double free
    BN_CTX_free(ctx);
    return 0;
}
----------

Nenhum comentário:

Postar um comentário

Comentários são moderados visando evitar spams e permitir discussões sadias.