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

时间:2014-01-15 22:51:40

标签: c encryption openssl blowfish

我正在尝试使用OpenSSL库来使用Blowfish的CBC块模式加密和解密字符串。出于平台原因,这需要在直接C而不是C ++中完成。由于某些原因,当输入字符串超过8个字符(1个块)时,输出的大小会急剧增加。

例如:加密abcdefgh将生成长度为8个字符的输出 - 一切都很好。但是,加密abcdefgha会产生699个字符长的字符!

我在做这个库的根本错误吗?据我所知,Blowfish的输出应该与输入的大小相同。任何人都可以解释我的错误吗?如果这是正确的,我如何知道创建输出缓冲区有多大,因为当输入超过1个块时,此代码会超出它。

以下代码示例:

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

1 个答案:

答案 0 :(得分:3)

当您的输入字符串被加密时,结果数据不再是您可以使用strlen()来获取其长度的字符串。您只能将数据视为二进制流。

由于Blowfish是分组密码,因此必须确保输入是块大小的倍数,如果输入长度不合适,则必须注意填充。当您为简单测试进行适当的填充时,输出长度与您的输入相同。

您可以使用更高级别的EVP加密/解密函数http://linux.die.net/man/3/evp_encryptinit,默认情况下启用填充。