协助openssl blowfish简单示例插入垃圾字符

如果您有一个很好的例子,只需使用openssl加密文件,这比我遇到问题的文件更好,我将非常感激。

更新:作者Myabe是正确的。 在我没有分配的东西上使用memset让我想起strtok对非堆栈变量的窒息。

Update2:使用malloc使核心转储停止。 更新了代码。 控件Hs仍在出现。 更新代码以反映这一点。

Update3:示例中的循环结构显示不正确。 我不确定后续读取的发生方式是否大于初始读取的大小。

Update4:我想我找到了。 decrypt loop有一个olen + = tlen,缓冲区应丢弃该组位。 :( 不是。

Update99988:我已经放弃了所有的希望。 我想我需要抛弃这个例子,而是从Openssl书中开始。 在解密时,中间层缓冲区预先添加了^ H,但由于指针被传入,我开始怀疑对齐问题。

我想我可能在一个糟糕的例子开始的船上比从头开始更糟糕。 我不得不做一些更正(原件在下面的代码中注释)。 原作者在传递地址方面存在一些问题。 作者使用的1024和1032不同大小的缓冲区正在激发我的思想,但我认为它与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 

坏代码警告坏代码使用来自选定答案的blowfish.c代码

 #include  #include  #include  #include  #include  #include  #include  #include  #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的方式有关。 应该在for循环结束时调用这些函数,也是在olen中添加tlen并再次写入的最后部分是复制输出。 以下是最终的工作版本:

 #include  #include  #include  #include  #include  #include  #include  #include  #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不会带你超过缓冲区的末尾吗?