Criptografia

Esse é um programa simples de criptografia que usa um algoritmo XOR (exclusivamente ou) escrito em C. Você o chama com o arquivo que será encriptado e com o nome do arquivo de saída; ele pede uma senha e criptografa esse arquivo usando essa senha. Para descriptografar, basta usar o programa novamente com a mesma senha. Assim:

crypt "arquivo de entrada.txt" "criptografado.txt"
crypt "criptografado.txt" "arquivo de saída.txt"

Se a senha for igual nas duas vezes, o arquivo será descriptografado, e o arquivo de entrada.txt será igual ao arquivo de saída.txt. O mais interessante do algoritmo XOR é você não precisar implementar um algoritmo para criptografar e outro para descriptografar, um único algoritmo faz todo o trabalho.

Quem é esse tal de XOR?

O XOR é um operador que atua nos bits e é representado em C pelo símbolo ^. Ele compara dois bits e dependendo deles, seu resultado será:

Bit 1 Bit 2 Resultado
0 0 0
1 0 1
0 1 1
1 1 0

Ou seja, comparando 11 (1011) e 12 (1100), teremos:

1011 (11)
1100 (12)
0111 (7)

Como chars tem a mesma representação interna de um inteiro, é isso que acontece ao usar o algoritmo XOR. Ele compara uma string com o texto original com a senha, usando XOR, e salva o resultado no arquivo de saída.

Código, eu quero o código

Primeiro incluímos as bibliotecas. Acho que a biblioteca termios.h é dependente da plataforma, e pode ser que usuários do Windows (e talvez outras plataformas unix-like que não sejam o Linux) tenham que achar outro jeito de impedir que os caracteres sejam impressos na tela. É ela que permite que programas como o sudo peçam a senha e quando você digitar, os caracteres não apareçam.

Também definimos um limite máximo para a senha. 32 me parece um bom número, já que dificilmente alguém vai lembrar uma senha desse tamanho.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#define PASSMAX 32

Essas são as funções que nós iremos usar:

char *encrypt( const char *text, const char *key, int size );
char *get_from_file( FILE *fileptr );
FILE *xfopen( const char *filename, const char *options );
int filesize( FILE *fileptr );
void to_file( const char *str, FILE *fileptr, int num );
void *xcalloc( size_t number, size_t size );
  • encrypt encripta e retorna o conteúdo de text, de tamanho size, usando a senha key.
  • get_from_file retorna em uma string todo o conteúdo do arquivo fileptr.
  • xfopen abre o arquivo filename com as opções options. Ela é uma versão “segura” de fopen, já que ela verifica se o arquivo foi aberto com sucesso.
  • filesize retorna o tamanho do arquivo fileptr em número de caracteres.
  • to_file salva o conteúdo da string str, de tamanho num, no arquivo fileptr.
  • xcalloc é, assim como xfopen, uma versão segura de calloc. A diferença entre calloc e malloc é que malloc só aloca a memória, calloc também limpa-a.

Abaixo está todo o código. Os comentários são bem explicativos, mas qualquer dúvida, comentem.

O motivo para as funções xfopen e xcalloc é simples: geralmente quando se chama uma dessas funções, deve-se verificar se o ponteiro é nulo; para facilitar, criei essas funções (o acréscimo de x na frente é um padrão do manual do GNU). E por que criar funções para salvar no arquivo, lê-lo, etc? Como estamos trabalhando com arquivos criptografados, muitas vezes surgem caracteres não imprimíveis. Pior ainda, pode surgir um caractere nulo no meio de uma string, o que faria com que o programa interpretasse aquilo como o fim da string.

/* crypt:
* crypt input output key
*
* Autor: André Ramaciotti da Silva
* Versão: 0.3
*
* Esse programa abre o arquivo determinado pelo primeiro argumento (input) e
* criptografa-o usando um algoritmo que usa o operador lógico ^ (XOR) e a
* chave (key) que foi dada como terceiro argumento.
*
* O resultado é gravado no arquivo dado pelo segundo argumento (output). No
* atual estado, deve-se tomar cuidado, pois se já houver um arquivos com o
* nome do segundo argumento, este será sobrescrito.
*
* NOTAS DA VERSÃO:
* Modificado para ser complacente com a última versão do C. Faltam ainda
* modificações no que diz respeito a sobrescrever um arquivo (-f).
*
* ESTE CÓDIGO ESTÁ EM DOMÍNIO PÚBLICO
*/

#include
#include
#include
#include /* struct termios */

#define PASSMAX 32 /* tamanho máximo da senha */

/* Criptografa o *text* do primeiro argumento usando a *key* do segundo e
* retorna uma string com o resultado */
char *encrypt( const char *text, const char *key, int size );

/* Retorna uma string com todo o conteudo do arquivo *fileptr* */
char *get_from_file( FILE *fileptr );

/* Abre o arquivo *filename* com as opções *options*. Se bem sucedido, retorna
* um ponteiro para o arquivo, se não, aborta a execução do programa. */
FILE *xfopen( const char *filename, const char *options );

/* Retorna o tamanho do arquivo *fileptr* em número de caracteres */
int filesize( FILE *fileptr );

/* Salva *num* caracteres da string *str* no arquivo *fileptr*. Útil se houver
* algum caractere nulo em meio à string */
void to_file( const char *str, FILE *fileptr, int num );

/* Aloca memória usando calloc e verifica se foi bem sucedido. Se for, retorna
* o(s) ponteiros, se não for, aborta a execução do programa */
void *xcalloc( size_t number, size_t size );

/* AQUI COMEÇA O PROGRAMA */
int main( int argc, char* argv[] )
{
char *encrypted = NULL; /* string encriptada */
char key[ PASSMAX+1 ]; /* senha */
char *string = NULL; /* string original */

FILE *input = NULL; /* arquivo de entrada */
FILE *output = NULL; /* arquivo de saída */

int size; /* tamanho do arquivo em número de caracteres */

struct termios def_termios, new_termios; /* estrutura com informações sobre o terminal */

if( argc != 3 ) /* verifica se foi chamado com os argumentos corretos */
{
fprintf( stderr, “Usage:\ncrypt inputfile outputfile\n”);
exit(EXIT_FAILURE);
}

input = xfopen( argv[1], “r” ); /* abre arquivo de entrada (“r”ead) */

/* Aqui usaremos fopen pois é permitido que o arquivo não exista */
output = fopen( argv[2], “r” ); /* usamos “r”, pois “w” iria sobrescrevê-lo */
if( output ) /* se o arquivo já existir, não vamos sobrescrevê-lo */
{
fprintf( stderr, “File exists: %s.\n”, argv[2]);
exit(EXIT_FAILURE);
}

output = xfopen( argv[2], “w” ); /* se não existia, agora o criamos (“w”rite) */

tcgetattr( fileno( stdin ), &def_termios ); /* descobrimos os atributos do terminal */
new_termios = def_termios; /* copiamos os atributos para uma nova estrutura */
new_termios.c_lflag &= ~ECHO; /* novo terminal não irá imprimir na tela */

printf(“Password: “);

/* tentamos atribuir as novas opções ao terminal */
if( tcsetattr( fileno( stdin ), TCSAFLUSH, &new_termios ) != 0 ) /* se não conseguir: */
{
fprintf( stderr, “Unable to set password (termios fault).\n” );
exit(EXIT_FAILURE);
}

else /* se conseguir: */
{
fgets( key, PASSMAX, stdin); /* pega a senha */
tcsetattr( fileno( stdin ), TCSANOW, &def_termios ); /* volta a como era antes */
}

printf(“\n”);

size = filesize( input ); /* descobrimos o tamanho do arquivo (quantidade de caracteres) */

string = (char *) xcalloc( size, sizeof( char ) ); /* alocamos a memória para guardá-lo */
encrypted = (char *) xcalloc( size, sizeof( char ) ); /* e para encriptá-lo. */

string = get_from_file( input ); /* salvamos todo o conteúdo numa string */

encrypted = encrypt( string, key, size ); /* encriptamos o conteúdo */
to_file( encrypted, output, size ); /* e salvamos o que criptografado */

fclose( input );
fclose( output );

exit( EXIT_SUCCESS );
}

void *xcalloc( size_t number, size_t size ) /* versão “segura” de calloc */
{
void *ptr = NULL;

ptr = calloc( number, size ); /* chama calloc */

if( ptr == NULL ) /* e verifica se foi bem sucedido */
exit( EXIT_FAILURE );

return ptr;
}

FILE *xfopen( const char *filename, const char *options ) /* versão “segura” de fopen */
{
FILE *file = fopen( filename, options ); /* chama fopen */
if( file == NULL ) /* e verifica se foi bem sucedido */
exit( EXIT_FAILURE );

return file;
}

char *encrypt( const char *text, const char *key, int size ) /* criptografa */
{
char *str = NULL; /* string criptografada */
int scount, kcount; /* contagem da string e da senha para o loop */

str = (char *) xcalloc( size, sizeof( char ) );

for( scount = 0, kcount = 0; scount < size; scount++, kcount++) /* enquanto não chegar ao tamanho da string ... */ { str[scount] = (text[scount] ^ key[kcount]); /* (des)criptografa usando XOR */ if( kcount == (strlen( key ) -1) ) /* reseta contagem da senha quando necessário */ { kcount = -1; } } str[ size ] = ''; /* termina string com 'null' */ return str; free( str ); } int filesize( FILE *fileptr ) /* acha tamanho do arquivo em número de caracteres */ { char c; int count = 0; while( c != EOF ) { c = fgetc( fileptr ); count++; } rewind( fileptr ); return count; } char *get_from_file( FILE *fileptr ) /* adquire string de um arquivo */ { int size, i; char *str; size = filesize( fileptr ); str = (char *) xcalloc( size, sizeof( char ) ); for( i = 0; i < size; i++ ) { str[i] = fgetc( fileptr ); } str[size-1] = ''; return str; free( str ); } void to_file( const char *str, FILE *fileptr, int num ) /* salva string em um arquivo */ { int i; for( i = 0; i < (num-1); i++ ) { fputc( str[i], fileptr ); } } [/sourcecode]

Publicidade

5 Respostas para “Criptografia

  1. Pingback: Criptografia II « Aletéia

  2. bruno novembro 6, 2011 às 11:30 pm

    olá tentei compilar através do dev c++,mas esta dando problema com a biblioteca termio.h poderia me ajudar…preciso de um programa que criptografe e descriptografe um arquivo txt com senha

  3. bg novembro 28, 2011 às 8:32 am

    Esse programa não copila!!!

  4. rafaelcapucho julho 13, 2012 às 3:44 am

    Compilando no Ubuntu 11.04 com GCC eu recebo este erro:

    teste2-xor.c: In function ‘encrypt’:
    teste2-xor.c:162:16: error: empty character constant
    teste2-xor.c: In function ‘get_from_file’:
    teste2-xor.c:196:16: error: empty character constant

    Aí então eu troquei as atribuições nessas linhas de = ”; para = NULL; e funcionou corretamente, houveram warnings mas funcionou.

    teste2-xor.c: In function ‘encrypt’:
    teste2-xor.c:162:14: warning: assignment makes integer from pointer without a cast
    teste2-xor.c: In function ‘get_from_file’:
    teste2-xor.c:196:14: warning: assignment makes integer from pointer without a cast

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: