2009-06-14 4 views
4

Если у вас есть хороший пример простого шифрования файла с помощью openssl, который лучше, чем тот, с которым у меня возникают проблемы, я был бы очень благодарен.Помощь с opensl blowfish простой пример вставки символов мусора

Обновление: Myabe автор был прав. Использование memset для чего-то, что я не выделял, напоминает мне strtok, задыхаясь от нестационарных переменных.

Update2: Получил дамп ядра, чтобы остановить использование malloc. Обновлен код. Управление Hs все еще появляется. Обновление кода, чтобы отразить это.

Update3: В примере пример структуры цикла не отображается правильно. Я не уверен, как последующие чтения превышают размер начального чтения.

Update4: Я думаю, что нашел. цикл дешифрования имеет olen + = tlen, и буфер должен отбросить этот набор бит. . :(не так

Update99988:. Я дал всякую надежде здесь я думаю, что нужно выбросить этот пример и начать что-то из книги OpenSSL вместо После расшифровки среднего слоя буферов preappended с.^H, но поскольку указатель передан, я начинаю подозревать проблемы с выравниванием.

Я думаю, что я могу быть в лодке, начиная с плохого примера, хуже, чем начинать с нуля. Мне пришлось внести некоторые исправления (оригинал аннотируется в коде ниже). У первоначального автора были некоторые проблемы с неправильным прохождением адресов. Мое сознание вызывается буферами различного размера, которые автор использует 1024 и 1032, но я думаю, что это связано d для 8-битных семенных и закодированных вызовов шифрования.

Я получаю символы мусора в (control Hs), а дамп ядра, такой как дешифрование, искажает стек. Я довольно новичок в шифровании, openssl, и я не так хорошо знаком с gdb.

Я сделал все возможное, чтобы упростить это вниз

  1. НКУ --version сообщает 4.3.2
  2. Open SUSE 11

compile.sh

gcc -g -o blowfish blowfish.c -lcrypto 

run.sh

ulimit -c unlimited 
./blowfish example.txt encrypted_example decrypted_example 
echo diff example.txt decrypted_example 
diff example.txt decrypted_example 

clean.sh

rm -rf blowfish encrypted_example decrypted_example core 

example.txt

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu 
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in 
culpa qui officia deserunt mollit anim id est laborum. 

Hydrogen H 
Helium H 
Lithium L 
Beryllium B 
Boron B 
Carbon C 
Nitrogen N 
Oxygen O 
Fluorine F 
Neon N 
Sodium N 
Magnesium M 
Aluminium A 
Silicon S 
Phosphorus P 
Sulfur S 
Chlorine C 
Argon A 
Potassium K 
Calcium C 
Scandium S 
Titanium T 
Vanadium V 
Chromium C 
Manganese M 
Iron F 
Cobalt C 
Nickel N 
Copper C 
Zinc Z 
Gallium G 
Germanium G 
Arsenic A 
Selenium S 
Bromine B 
Krypton K 
Rubidium R 
Strontium S 
Yttrium Y 
Zirconium Z 
Niobium N 
Molybdenum M 
Technetium T 
Ruthenium R 
Rhodium R 
Palladium P 
Silver A 
Cadmium C 
Indium I 
Tin S 
Antimony S 
Tellurium T 
Iodine I 
Xenon X 
Caesium C 
Barium B 
Lanthanum L 
Cerium C 
Praseodymium P 
Neodymium N 
Promethium P 
Samarium S 
Europium E 
Gadolinium G 
Terbium T 
Dysprosium D 
Holmium H 
Erbium E 
Thulium T 
Ytterbium Y 
Lutetium L 
Hafnium H 
Tantalum T 
Tungsten W 
Rhenium R 
Osmium O 
Iridium I 
Platinum P 
Gold A 
Mercury H 
Thallium T 
Lead P 
Bismuth B 
Polonium P 
Astatine A 
Radon R 
Francium F 
Radium R 
Actinium A 
Thorium T 
Protactinium P 
Uranium U 
Neptunium N 
Plutonium P 
Americium A 
Curium C 
Berkelium B 
Californium C 
Einsteinium E 
Fermium F 
Mendelevium M 
Nobelium N 
Lawrencium L 
Rutherfordium R 
Dubnium D 
Seaborgium S 
Bohrium B 
Hassium H 
Meitnerium M 
Darmstadtium D 
Roentgenium R 
Ununbium U 
Ununtrium U 
Ununquadium U 
Ununpentium U 
Ununhexium U 
Ununseptium U 
Ununoctium U 

плохой код ПРЕДУПРЕЖДЕНИЕ BAD КОД КОД использования от выбранного ответа Blowfish.с

#include <openssl/blowfish.h> 
#include <openssl/evp.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <string.h> 
#define IP_SIZE 1024 
#define OP_SIZE 1032 
unsigned char key[16]; 
unsigned char iv[8]; 

int 
generate_key() 
{ 
    int i, j, fd; 
    if ((fd = open ("/dev/random", O_RDONLY)) == -1) 
    perror ("open error"); 

    if ((read (fd, key, 16)) == -1) 
    perror ("read key error"); 

    if ((read (fd, iv, 8)) == -1) 
    perror ("read iv error"); 

    printf ("128 bit key:\n"); 
    for (i = 0; i < 16; i++) 
    printf ("%4d ", key[i]); 

    printf ("\nInitialization vector\n"); 
    for (i = 0; i < 8; i++) 
    printf ("%4d ", iv[i]); 
    printf ("\n"); 


    close (fd); 
    return 0; 
} 

int 
decrypt (int infd, int outfd) 
{ 
    char *inbuff, *outbuf; 
    int olen, tlen, n; 
    EVP_CIPHER_CTX ctx; 
    EVP_CIPHER_CTX_init (&ctx); 
    EVP_DecryptInit (&ctx, EVP_bf_cbc(), key, iv); 

    outbuf = (unsigned char *) malloc (sizeof(unsigned char) * IP_SIZE); 
    inbuff = (unsigned char *) malloc (sizeof(unsigned char) * OP_SIZE); 

    /* keep reading until a break */ 
    for (;;) 
    { 
     memset(inbuff,'\0', OP_SIZE); 
     if ((n = read (infd, inbuff, OP_SIZE)) == -1) 
    { 
     perror ("read error"); 
     break; 
    } 
     else if (n == 0) 
    break; 

     memset(outbuf,'\0', IP_SIZE); 

     if (EVP_DecryptUpdate (&ctx, outbuf, &olen, inbuff, n) != 1) 
    { 
     printf ("error in decrypt update\n"); 
     return 0; 
    } 

     if (EVP_DecryptFinal (&ctx, outbuf + olen, &tlen) != 1) 
    { 
     printf ("error in decrypt final\n"); 
     return 0; 
    } 
     olen += tlen; 
     if ((n = write (outfd, outbuf, olen)) == -1) 
    perror ("write error"); 
    } 

    EVP_CIPHER_CTX_cleanup (&ctx); 
    return 1; 
} 

int 
encrypt (int infd, int outfd) 
{ 
    char *inbuff, *outbuf; 

    int olen, tlen, n; 
    EVP_CIPHER_CTX ctx; 
    EVP_CIPHER_CTX_init (&ctx); 
    EVP_EncryptInit (&ctx, EVP_bf_cbc(), key, iv); 

    outbuf = (unsigned char *) malloc (sizeof(unsigned char) * OP_SIZE); 
    inbuff = (unsigned char *) malloc (sizeof(unsigned char) * IP_SIZE); 

    for (;;) 
    { 
     memset(inbuff,'\0', IP_SIZE); 

     if ((n = read (infd, inbuff, IP_SIZE)) == -1) 
    { 
     perror ("read error"); 
     break; 
    } 
     else if (n == 0) 
    break; 

     if (EVP_EncryptUpdate (&ctx, outbuf, &olen, inbuff, n) != 1) 
    { 
     printf ("error in encrypt update\n"); 
     return 0; 
    } 

     if (EVP_EncryptFinal (&ctx, outbuf + olen, &tlen) != 1) 
    { 
     printf ("error in encrypt final\n"); 
     return 0; 
    } 
     olen += tlen; 
     if ((n = write (outfd, outbuf, olen)) == -1) 
    perror ("write error"); 
    } 
    EVP_CIPHER_CTX_cleanup (&ctx); 
    return 1; 
} 

int 
main (int argc, char *argv[]) 
{ 
    int flags1 = 0, flags2 = 0, outfd, infd, decfd; 
    mode_t mode; 
    char choice, temp; 
    int done = 0, n, olen; 

    memset(key,'\0', 16); 
    memset(iv,'\0', 8); 
    memset(&mode, '\0', sizeof(mode)); 

    flags1 = flags1 | O_RDONLY; 
    flags2 = flags2 | O_RDONLY; 
    flags2 = flags2 | O_WRONLY; 
    flags2 = flags2 | O_CREAT; 

    mode = mode | S_IRUSR; 
    mode = mode | S_IWUSR; 

    generate_key(); 

    if ((infd = open (argv[1], flags1, mode)) == -1) 
    perror ("open input file error"); 

    if ((outfd = open (argv[2], flags2, mode)) == -1) 
    perror ("open output file error"); 

    encrypt (infd, outfd); 

    close (infd); 
    close (outfd); 

    if ((outfd = open (argv[2], flags1, mode)) == -1) 
    perror ("open output file error"); 

    if ((decfd = open (argv[3], flags2, mode)) == -1) 
    perror ("open output file error"); 

    /* After much head scratching reusing the out as an in is correct here */ 
    decrypt (outfd, decfd); 

    close (outfd); 
    fsync (decfd); 
    close (decfd); 

    return 0; 
} 
+0

Как вы рассчитываете OP_SIZE? – Oscar

ответ

8

Ошибка в способе вызова EVP_DecryptFinal и EVP_EncryptFinal. Эти функции должны быть вызваны в конце цикла for, а также окончательная часть, в которую добавляется olen, и снова записывается дублирование вывода. Ниже приведена окончательная рабочая версия:

#include <openssl/blowfish.h> 
#include <openssl/evp.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <string.h> 
#define IP_SIZE 1024 
#define OP_SIZE 1024 + EVP_MAX_BLOCK_LENGTH 
unsigned char key[16]; 
unsigned char iv[8]; 

int 
generate_key() 
{ 
    int    i, fd; 
    if ((fd = open("/dev/random", O_RDONLY)) == -1) 
     perror("open error"); 

    if ((read(fd, key, 16)) == -1) 
     perror("read key error"); 

    if ((read(fd, iv, 8)) == -1) 
     perror("read iv error"); 

    printf("128 bit key:\n"); 
    for (i = 0; i < 16; i++) 
     printf("%4d ", key[i]); 

    printf("\nInitialization vector\n"); 
    for (i = 0; i < 8; i++) 
     printf("%4d ", iv[i]); 
    printf("\n"); 


    close(fd); 
    return 0; 
} 

int 
do_decrypt(int infd, int outfd) 
{ 
    unsigned char   *inbuff, *outbuf; 
    int    olen=0, tlen=0, n=0; 
    EVP_CIPHER_CTX ctx; 
    EVP_CIPHER_CTX_init(&ctx); 
    EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv); 

    outbuf = (unsigned char *) malloc(sizeof(unsigned char) * OP_SIZE); 
    inbuff = (unsigned char *) malloc(sizeof(unsigned char) * IP_SIZE); 

    /* keep reading until a break */ 
    for (;;) { 
     memset(inbuff, 0, IP_SIZE); 
     if ((n = read(infd, inbuff, IP_SIZE)) == -1) { 
      perror("read error"); 
      break; 
     } else if (n == 0) 
      break; 

     memset(outbuf, 0, OP_SIZE); 

     if (EVP_DecryptUpdate(&ctx, outbuf, &olen, inbuff, n) != 1) { 
      printf("error in decrypt update\n"); 
      return 0; 
     } 
     if ((n = write(outfd, outbuf, olen)) == -1) 
      perror("write error"); 
    } 

    tlen=0; 
    if (EVP_DecryptFinal(&ctx, outbuf + olen, &tlen) != 1) { 
     perror("error in decrypt final"); 
     return 0; 
    } 

    if ((n = write(outfd, outbuf+olen, tlen)) == -1) 
     perror("write error"); 

    EVP_CIPHER_CTX_cleanup(&ctx); 
    return 1; 
} 

int 
do_encrypt(int infd, int outfd) 
{ 
    unsigned char   *inbuff, *outbuf; 

    int    olen=0, tlen=0, n=0; 
    EVP_CIPHER_CTX ctx; 
    EVP_CIPHER_CTX_init(&ctx); 
    EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv); 

    outbuf = (unsigned char *) malloc(sizeof(unsigned char) * OP_SIZE); 
    inbuff = (unsigned char *) malloc(sizeof(unsigned char) * IP_SIZE); 

    for (;;) { 
     memset(inbuff, 0, IP_SIZE); 

     if ((n = read(infd, inbuff, IP_SIZE)) == -1) { 
      perror("read error"); 
      break; 
     } else if (n == 0) 
      break; 

     if (EVP_EncryptUpdate(&ctx, outbuf, &olen, inbuff, n) != 1) { 
      printf("error in encrypt update\n"); 
      return 0; 
     } 

     if ((n = write(outfd, outbuf, olen)) == -1) 
      perror("write error"); 
    } 
    tlen=0; 
    if (EVP_EncryptFinal(&ctx, outbuf + olen, &tlen) != 1) { 
     printf("error in encrypt final\n"); 
     return 0; 
    } 

    if ((n = write(outfd, outbuf+olen, tlen)) == -1) 
     perror("write error"); 

    EVP_CIPHER_CTX_cleanup(&ctx); 
    return 1; 
} 

int 
main(int argc, char *argv[]) 
{ 
    int    flags1 = 0, flags2 = 0, outfd, infd; 
    mode_t   mode; 

    memset(key, 0, 16); 
    memset(iv, 0, 8); 
    memset(&mode, 0, sizeof(mode)); 

    flags1 = flags1 | O_RDONLY; 
    flags2 = flags2 | O_RDONLY; 
    flags2 = flags2 | O_WRONLY; 
    flags2 = flags2 | O_CREAT; 

    mode = mode | S_IRUSR; 
    mode = mode | S_IWUSR; 


    generate_key(); 


    if ((infd = open(argv[1], flags1, mode)) == -1) 
     perror("open input file error"); 

    if ((outfd = open(argv[2], flags2, mode)) == -1) 
     perror("open output file error"); 

    do_encrypt(infd, outfd); 

    close(infd); 
    fsync(outfd); 
    close(outfd); 

    if ((infd = open(argv[2], flags1, mode)) == -1) 
     perror("open output file error"); 

    if ((outfd = open(argv[3], flags2, mode)) == -1) 
     perror("open output file error"); 

    do_decrypt(infd, outfd); 

    close(infd); 
    fsync(infd); 
    close(outfd); 

    return 0; 
} 
+0

Я серьезно сомневаюсь в этом. Если бы это было так, то последнее количество бит мы выписали дважды. – ojblass

+0

Из моего понимания блок-шифров это имеет смысл. * Конечные функции используются для последних бит данных, которые не кратно размеру блока. Кроме того, тот факт, что вы выполняете * Заключительный вызов функции внутри цикла, является причиной символов мусора в расшифрованном файле. В моем тесте это решило проблему – rsarro

+0

, мой предыдущий ответ был не совсем прав. Последнее редактирование - это полная рабочая версия, основанная на коде в вашем вопросе (с исправлениями и некоторыми исправлениями). – rsarro

1

Так вы говорите, кажется, ошибка будет приходить на этапе дешифрования, я бы посмотрел с подозрением на этих линиях:

if (EVP_DecryptUpdate (&ctx, outbuf, &olen, inbuff, n) != 1) 
... 

if (EVP_DecryptFinal (&ctx, outbuf + olen, &tlen) != 1) 
... 

Насколько велика память, выделенная для outbuf по отношению к какие функции дешифрования будут помещены в них? Вы уверены, что outbuf + olen не собирается проходить мимо конца буфера?

+0

Его очень сложно сказать, поврежден ли он при шифровании или расшифровке времени. #define IP_SIZE 1024 #define OP_SIZE 1032 char outbuf [OP_SIZE]; символ inbuff [IP_SIZE]; – ojblass

+0

Я позволил сделать memset на то, что я не выделил? – ojblass

+0

hmmm, который мог бы объяснить использование авторами & outbuf в своих командах bzero ... попытаться выделить вместо переменных стека. – ojblass