简体   繁体   English

C中的河豚CBC模式和缓冲区溢出

[英]Blowfish CBC mode and Buffer Overrun in C

I am trying to use the OpenSSL library to encrypt and decrypt a string using the CBC block mode of Blowfish. 我正在尝试使用Blowfish的CBC阻止模式使用OpenSSL库对字符串进行加密和解密。 For platform reasons this needs to be done in straight-C rather than C++. 出于平台原因,这需要使用C语言而不是C ++语言来完成。 For some reason when the input string is longer than 8 characters (1 block), the size of the output increases dramatically. 由于某些原因,当输入字符串超过8个字符(1个块)时,输出的大小会急剧增加。

For example: encrypting abcdefgh will generate an output 8 chars in length - all is good. 例如:加密abcdefgh将生成长度为8个字符的输出-一切都很好。 However, encrypting abcdefgha will generate an output 699 chars long! 但是,加密abcdefgha将产生一个长699个字符的输出!

Am I doing something fundamentally wrong with this library? 我在这个库中做错了什么吗? It was my understanding that the output from Blowfish should be the same size as the input. 据我了解,河豚的输出应与输入的大小相同。 Can anyone explain what I'm doing wrong with this? 谁能解释我对此做错了什么? If this is correct, how can I tell how big to create the output buffer as this code overruns it when the input is over 1 block. 如果这是正确的,那么当输入超过1个块时,由于这段代码会溢出该代码,我该如何判断输出缓冲区的大小。

Code sample below: 下面的代码示例:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <openssl/blowfish.h>
const unsigned char* BLOWFISH_KEY = "TestKey!";
#define SIZE 8

unsigned char* blowfish_decrypt(unsigned char* in);
unsigned char* blowfish_encrypt(unsigned char* in);

int main(){

    char* message   = "abcdefgha";

    char* encrypted = blowfish_encrypt(message);
    printf("Encrypted: %s\n", encrypted);
    printf("Size of encrypted: %d\n\n", strlen(encrypted));

    char* decrypted = blowfish_decrypt(encrypted);
    printf("Decrypt: %s\n", decrypted);
    printf("Size of encrypted: %d\n\n", strlen(encrypted));
    return 0;

}

unsigned char* blowfish_encrypt(unsigned char* in){

  int i;
  int SIZE_IN = strlen(in);
  unsigned char *out = calloc(SIZE_IN+1, sizeof(char));

  char ivec[8];
  for(i=0; i<8; i++) ivec[i] = 'i';

  BF_KEY *key = calloc(1, sizeof(BF_KEY));

  /* set up a test key */
  BF_set_key(key, SIZE, BLOWFISH_KEY );

  BF_cbc_encrypt(in, out, strlen(in), key, ivec, BF_ENCRYPT);

  printf("Size of out: %d\n", strlen(out));
  printf("Size of in: %d\n", strlen(in));
  return out;
}

unsigned char* blowfish_decrypt(unsigned char* in){

  int i;
  int SIZE_IN = strlen(in);
  unsigned char *out = calloc(SIZE_IN+1, sizeof(char));

  char ivec[8];
  for(i=0; i<8; i++) ivec[i] = 'i';

  BF_KEY *key = calloc(1, sizeof(BF_KEY));

  /* set up a test key */
  BF_set_key(key, SIZE, BLOWFISH_KEY );

  BF_cbc_encrypt(in, out, strlen(in), key, ivec, BF_DECRYPT);

  printf("Size of out: %d\n", strlen(out));
  printf("Size of in: %d\n", strlen(in));
  return out;
}

When your input string is encrypted, the resulting data is no longer a string that you could use strlen() to get its length. 输入字符串加密后,结果数据不再是可以使用strlen()获取其长度的字符串。 You could only treat the data as binary stream. 您只能将数据视为二进制流。

Since Blowfish is a block cipher, you have to ensure your input is a multiple of the the block size, and you have to take care of the padding if input length does not fit. 由于Blowfish是块密码,因此必须确保输入的值是块大小的倍数,并且如果输入长度不合适,则必须注意填充。 The output length is the same as your input when you do the proper padding for your simple test. 为简单测试进行适当的填充时,输出长度与输入长度相同。

You could use the higher level of EVP encrypt/decrypt functions http://linux.die.net/man/3/evp_encryptinit , padding is enable by default. 您可以使用更高级别的EVP加密/解密功能http://linux.die.net/man/3/evp_encryptinit ,默认情况下启用填充。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM