Помощь с openssl blowfish простой пример вставки мусорных символов - PullRequest
4 голосов
/ 15 июня 2009

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

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

Обновление2: Получил дамп ядра для остановки с помощью malloc. Обновил код. Контрольные Hs все еще появляются. Обновление кода для отражения этого.

Обновление3: Структура цикла в этом примере выглядит неправильно. Я не уверен, как последующие чтения происходят больше, чем размер первоначального чтения.

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

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

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

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

Я приложил все усилия, чтобы упростить это

  1. gcc - отчеты о версиях 4.3.2
  2. Открыть 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

ПРЕДУПРЕЖДЕНИЕ КОДА ПЛОХОГО КОДА ИСПОЛЬЗОВАНИЕ КОДА ПЛОХОГО ОТ ВЫБОРА ОТВЕТА blowfish.c

#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;
}

Ответы [ 2 ]

8 голосов
/ 16 июня 2009

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

#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;
}
1 голос
/ 15 июня 2009

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

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

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

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

...