質問

私が問題を抱えているこの例よりも優れた、openssl を使用してファイルを単純に暗号化する良い例があれば、非常に感謝します。

アップデート: 著者のミャベは正しかった。割り当てていないものに memset を使用すると、非スタック変数で strtok がチョークすることを思い出します。

アップデート2: mallocを使用してコアダンプを停止させました。コードを更新しました。コントロールの H はまだ表示されています。これを反映するようにコードを更新します。

アップデート3: この例では、ループ構造が正しく見えません。最初の読み取りのサイズを超える後続の読み取りがどのように発生するかはわかりません。

アップデート4: 見つけたと思います。復号ループには olen += tlen があり、バッファはそのビットのセットを破棄する必要があります。:( そうじゃない。

アップデート99988: 私はここですべての希望を捨てました。この例は捨てて、代わりに Openssl 本の内容から始める必要があると思います。復号化すると、中間層のバッファの前に ^H が追加されますが、ポインタが渡されるため、アライメントの問題が疑われ始めています。

私は、悪い例から始めるほうが、ゼロから始めるより悪いという考えに陥っているのかもしれません。いくつか修正する必要がありました(元のコードには以下の注釈が付けられています)。オリジナルの作成者は、アドレスを誤って渡すという問題を抱えていました。著者が使用している 1024 と 1032 という異なるサイズのバッファーに頭が混乱していますが、これは 8 ビット シードと連鎖暗号化呼び出しに関連していると思います。

(コントロール Hs) に文字化けが発生し、復号化のようなコア ダンプがスタックを破損しています。私は暗号化、openssl についてはかなり初心者で、gdb についてはあまり詳しくありません。

これを簡素化するためにあらゆる試みを行ってきました

  1. gcc --version は 4.3.2 を報告します
  2. SUSE 11 を開く

コンパイル.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

クリーン.sh

rm -rf blowfish encrypted_example decrypted_example core

例.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

不正なコードの警告 不正なコード 選択された回答のコードを使用してください bullfish.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;
}
役に立ちましたか?

解決

エラーがEVP_DecryptFinal及びEVP_EncryptFinalが呼ばれている方法です。これらの機能はまた、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;
}

他のヒント

あなたはエラーが復号化段階で来ているようだと言うので、私はこれらの行に疑いの目で見てます。

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

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

復号化機能は、それらの中に入れてされるものとの関係でoutbufのために割り当てられたメモリはどのくらいでしょうか?あなたは必ずoutbuf + olenがバッファの終わりを越えあなたを取るつもりはないされていますか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top