BF_set_key() vs EVP_CIPHER_CTX_set_key_length()

Tomas Mraz tomas at
Sat Apr 22 08:31:45 UTC 2023

This is the same problem as

You need to call EVP_CipherInit_ex() twice. First with just the
EVP_CIPHER parameter set, then set the key length and then call the
second init with the passwd, iv and NULL EVP_CIPHER.

You can also use the EVP_CipherInit_ex2() with params setting the key
length in the first call instead of calling
EVP_CIPHER_CTX_set_key_length() as a small optimization.

Tomas Mraz, OpenSSL

On Fri, 2023-04-21 at 15:44 -0700, Thomas Dwyer III wrote:
>  We have multiple versions of an application using blowfish that
> already shipped to customers. This legacy code uses the low level
> blowfish primitives and I'm trying to port it to the high level EVP
> APIs but I'm not getting the same results.
>  Old code:
>          BF_set_key(&key, plen, passwd);
>          BF_cfb64_encrypt(data, out, dlen, &key, iv, &offset,
>  New code (return code checking omitted for clarity):
>          ctx = EVP_CIPHER_CTX_new();
>          EVP_CipherInit_ex(ctx, EVP_bf_cfb64(), NULL, passwd, iv,
>          EVP_CIPHER_CTX_set_key_length(ctx, plen);
>          EVP_CipherUpdate(ctx, out, &outlen, data, dlen);
>          EVP_CipherFinal_ex(ctx, out+outlen, &outlen);
>  I expected the "out" buffer to contain the same value for both
> implementations. It doesn't. The problem appears to center around the
> length of the key but I'm not sure what's going wrong.
>  Unfortunately, a bug in the legacy code is effectively setting plen
> to strlen(passwd)+1 rather than strlen(passwd), causing the null
> terminator to be included in the length passed to BF_set_key(). For
> backward compatibility with code that already shipped, I attempted to
> preserve this buggy semantic in the new code by calling
> EVP_CIPHER_CTX_set_key_length() with the same value that was
> originally getting passed to BF_set_key().
>  If my key is more than 15 bytes long (e.g. "GoodMorningWorld") or
> less than 15 bytes long (e.g. "GoodMorningWor") then the old & new
> code produce different results. However, if the key is exactly 15
> bytes long (e.g. "GoodMorningWorl") then the old & new code both
> produce the same result. In fact, the call to
> EVP_CIPHER_CTX_set_key_length() does not appear to have any impact on
> the result (even though a subsequent EVP_CIPHER_CTX_key_length()
> returns this new value instead of the default 16). I don't understand
> this. What am I missing?
>  Thanks,
>  Tom.III

Tomáš Mráz, OpenSSL

More information about the openssl-users mailing list