EVP_密码_CTX_设置_密钥_长度接受河豚的错误大小

EVP_密码_CTX_设置_密钥_长度接受河豚的错误大小,c,openssl,C,Openssl,当我试图通过EVP\u CIPHER\u CTX\u set\u key\u length将EVP\u aes\u 128\u cbc信封的密钥长度设置为58时,我得到以下错误: 3073369856:error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length:crypto/evp/evp_enc.c:557: 这是有道理的,因为EVP_aes_128_cbc只支持128位或

当我试图通过
EVP\u CIPHER\u CTX\u set\u key\u length
EVP\u aes\u 128\u cbc
信封的密钥长度设置为58时,我得到以下错误:

3073369856:error:0607A082:digital envelope routines:EVP_CIPHER_CTX_set_key_length:invalid key length:crypto/evp/evp_enc.c:557:
这是有道理的,因为EVP_aes_128_cbc只支持128位或16字节的密钥大小

对我来说没有意义的是,当我为
EVP\u bf\u cbc
做同样的事情时,我一点错误都没有

根据数据,最大位大小为448位或56字节,小于58。此外,引用“OpenSSL对密钥大小设置了256位的硬限制”

我的代码:

#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <string.h>
void handleErrors(void);
int main (void)
{
  unsigned char *key = (unsigned char *)"0123456789012345678901234567890123456789012345678901234567";
  unsigned char *iv = (unsigned char *)"01234567";
  unsigned char *plaintext = (unsigned char *)"xxxxxxxx";
  unsigned char ciphertext[128];
  int plaintext_len = strlen((char *)plaintext);
  int len;
  EVP_CIPHER_CTX *ctx;
  ERR_load_crypto_strings();
  OpenSSL_add_all_algorithms();
  OPENSSL_config(NULL);
  if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
  if (!EVP_EncryptInit_ex(ctx, EVP_bf_cbc(), NULL, NULL, NULL)) handleErrors();
  if (!EVP_CIPHER_CTX_set_key_length(ctx, 58)) handleErrors();
  if (1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
  if (1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) handleErrors();
  if (1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
  EVP_CIPHER_CTX_free(ctx);
}
void handleErrors(void)
{
  ERR_print_errors_fp(stderr);
  abort();
}
#包括
#包括
#包括
#包括
#包括
无效句柄错误(无效);
内部主(空)
{
无符号字符*键=(无符号字符*)“0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567”;
无符号字符*iv=(无符号字符*)“01234567”;
无符号字符*明文=(无符号字符*)“xxxxxxxx”;
无符号字符密文[128];
int明文=strlen((char*)明文;
内伦;
EVP_CIPHER_CTX*CTX;
错误加载加密字符串();
OpenSSL_添加_所有算法();
OPENSSL_配置(空);
如果(!(ctx=EVP_CIPHER_ctx_new())句柄错误();
如果(!EVP_EncryptInit_ex(ctx,EVP_bf_cbc(),NULL,NULL))handleErrors();
如果(!EVP_CIPHER_CTX_set_key_length(CTX,58))句柄错误();
如果(1!=EVP_EncryptInit_ex(ctx,NULL,NULL,key,iv))handleErrors();
如果(1!=EVP_EncryptUpdate(ctx,密文,&len,明文,明文_len))handleErrors();
如果(1!=EVP_EncryptFinal_ex(ctx、密文+len和len))句柄错误();
无密码(CTX)的执行副总裁;
}
无效句柄错误(无效)
{
错误打印错误fp(stderr);
中止();
}

EVP_bf_cbc
替换为
EVP_aes_128_cbc
,以再现错误。如果我在
EVP_EncryptInit_ex
(使用
EVP_aes_128_cbc
)中出现错误,我不会感到惊讶,因为iv不等于块大小,但代码在该点之前就中止了,所以在我看来这似乎有点没有意义。

使用
EVP_CIPHER\u CTX\u set\u key\u length()
仅在密码具有可变密钥长度的情况下有用(对于河豚就是这样)。该函数对提供的密钥长度执行一些有限的验证。如果密码具有固定长度的密钥,那么它将检查提供的密钥长度是否与固定长度相同。否则它将返回一个错误

如果使用具有可变长度密钥的密码,则只检查密钥长度是否为正。否则,您可以设置任何您喜欢的值。这实际上没有什么区别,因为当河豚使用它时,它会检查键的长度是否正常,如果键太长,则使用缩短的长度:

static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                       const unsigned char *iv, int enc)
{
    BF_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key);
    return 1;
}
...
void BF_set_key(BF_KEY *key, int len, const unsigned char *data)
#ifdef OPENSSL_FIPS
{
    fips_cipher_abort(BLOWFISH);
    private_BF_set_key(key, len, data);
}

void private_BF_set_key(BF_KEY *key, int len, const unsigned char *data)
#endif
{
    int i;
    BF_LONG *p, ri, in[2];
    const unsigned char *d, *end;

    memcpy(key, &bf_init, sizeof(BF_KEY));
    p = key->P;

    if (len > ((BF_ROUNDS + 2) * 4))
        len = (BF_ROUNDS + 2) * 4;
这里BF_ROUNDS==16,因此最大密钥长度为72字节(576位)。我对河豚不是特别熟悉,所以我不知道为什么这个和你上面提到的448位之间有差异

编辑: 啊,这种差异可能是由以下原因造成的(来自维基百科):
“由于P-array的长度为576位,并且在初始化期间密钥字节通过所有576位进行异或运算,因此许多实现支持密钥大小高达576位。”

这可能是OpenSSL中的验证问题。我猜库在内部将密钥设置为56字节。也许你应该把它放在OpenSSL邮件列表上。“这里BF_ROUNDS==16,所以最大密钥长度是72字节(576位)。我对河豚并不特别熟悉,所以我不知道为什么它和你上面提到的448位之间会有差异”——Schneier说它的448位;看见可能是算法更新了。我刚刚试着用
EVP\u CIPHER\u CTX\u set\u key\u length()和
EVP\u bf\u cbc
传递100。没有任何错误。看看您发布的代码片段,这并不奇怪——如果大小太大并且是可变长度密码,它看起来只是默默地调整大小。似乎它应该给出一个错误。哦,好吧。。