2009-06-14 47 views
4

如果你有一個很好的例子,簡單地使用openssl加密一個比這個更好的文件來處理文件,我會非常感激。幫助openssl blowfish插入垃圾文字的簡單例子

更新:作者Myabe是正確的。在我沒有分配的東西上使用memset讓我想起了strtok在非堆棧變量上的窒息。

Update2:通過使用malloc獲得停止的核心轉儲。更新了代碼。對照Hs仍然出現。更新代碼以反映這一點。

Update3:示例中循環結構不正確。我不確定隨後的讀取發生的次數大於最初讀取的大小。

Update4:我想我找到了它。解密循環有一個olen + = tlen,緩衝區應丟棄該位。 。:(不是

Update99988: 我已經放棄了所有希望在這裏,我想我需要扔掉這個例子,並開始從Openssl的書,而不是東西解密後的中間層緩衝區preappended用。^H的,但自從一個指針通過我開始懷疑對齊問題

我認爲我可能在一個壞的例子開始的船比從頭開始更糟糕,我不得不作出一些更正(原始作者在下面的代碼中註明了)原作者在傳遞地址時遇到了一些問題,我的思想被作者使用1024和1032的不同大小的緩衝區所踢,但我認爲它是相關的d到8位種子和鏈式加密調用。

我得到垃圾字符(控制Hs)和像解密這樣的核心轉儲破壞了堆棧。我對加密,openssl,還不是很熟悉gdb。

我已經盡一切努力簡化下來

  1. 的gcc --version報告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 

BAD CODE警告BAD CODE使用代碼選自河豚ANSWER。ç

#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 2011-05-17 08:31:49

回答

8

錯誤在於調用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; 
} 
+0

我很懷疑這件事。如果這是真的,我們會寫出最後的比特數兩次。 – ojblass 2009-06-16 01:35:13

+0

從我對塊密碼的理解來看,這是有道理的。 *最終函數用於不是塊大小倍數的最後一位數據。另外,你在循環中做一個* Final函數調用的事實是解密文件中垃圾字符的原因。在我的測試中,這解決了問題 – rsarro 2009-06-16 08:42:25

+0

我以前的答案並不完全正確。最後的編輯是一個完整的工作版本,基於你的問題中的代碼(包括修復和一些清理)。 – rsarro 2009-06-19 20:34:30

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]; char inbuff [IP_SIZE]; – ojblass 2009-06-14 21:45:53

+0

我可以對我沒有分配的東西做一個memset嗎? – ojblass 2009-06-14 21:46:35

+0

嗯,這可能會解釋作者在他的bzero命令中使用&outbuf ...將嘗試分配而不是堆棧變量。 – ojblass 2009-06-14 21:47:40