Hi all, I am a C++ developer, and I need an implementation of blowfish encoding under linux. Everything seems working well if using BF_ functions, but I found some problems with EVP_bf interface, using key shorter than 128 bits.
This code exemplify the problem.

#include <string>
#include <iostream>
#include <sstream>
#include <openssl/evp.h>
#include <openssl/blowfish.h>

// print hexadecimal data of a string
std::string printHex(const std::string &data)
{
    std::stringstream ss;
    ss << std::hex << std::uppercase;
    for (size_t i = 0; i < data.size(); ++i)
    {
        ss << (int)(unsigned char)data[i];
    }
    return ss.str();
}

std::string testBF_ecb_encrypt(const std::string &in_data, const std::string &key)
{
    BF_KEY k;
    BF_set_key(&k, key.size(), (unsigned char *)key.c_str());
    // output buffer len
    size_t outlen = ((in_data.size() + 7) / 8) * 8;
    unsigned char * res = new unsigned char[outlen];
    // apply blowfish encryption, 8 bytes per step
    for (size_t i = 0; i < outlen / 8; ++i)
    {
BF_ecb_encrypt((unsigned char*)&in_data.c_str()[i * 8], &res[i * 8], &k, BF_ENCRYPT);
    }
    std::string result = std::string((char*)res, outlen);
    delete [] res;
    return result;
}

std::string testEVP_bf_ecb(std::string in_data, const std::string &key)
{

    // unused
    unsigned char iv[] = {0, 0, 0, 0, 0, 0, 0, 0};

    EVP_CIPHER_CTX ctx;
    EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx, EVP_bf_ecb(), NULL, (unsigned char *) key.c_str(), iv);
    // adapt key length
    if (!EVP_CIPHER_CTX_set_key_length(&ctx, key.size()))
    {
        return "";
    }
    // disable library padding
    EVP_CIPHER_CTX_set_padding(&ctx, 0);

    // data len
    size_t len = in_data.size();
    // padding
    in_data.append(8, '\0');
    in_data.resize(((len + 7) / 8) * 8);
    // output buffer, larger than necessary
    unsigned char * outbuf = new unsigned char[len + 8];
    //
    bool done = false;
    std::string result;
    int outlen, tmplen;

    len = in_data.size();
if(EVP_EncryptUpdate(&ctx, outbuf, &outlen, (unsigned char *) in_data.c_str(), len))
    {
        if(EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen))
        {
            outlen += tmplen;
            done = true;
        }
    }
    EVP_CIPHER_CTX_cleanup(&ctx);
    if (done)
    {
        result = std::string((char *)outbuf, outlen);
    }
    delete [] outbuf;
    return result;
}

int main(int argc, char **argv)
{
    std::string data("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8);
    std::string key("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8);
std::cout << "From http://www.schneier.com/code/vectors.txt, cipher bytes should be 51866FD5B85ECB8A" << std::endl; std::cout << "Test BF_ecb_encrypt(): " << printHex(testBF_ecb_encrypt(data, key)) << std::endl; std::cout << "Test EVP_bf_ecb(): " << printHex(testEVP_bf_ecb(data, key)) << std::endl; key = std::string("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0\0\0\0\0\0", 16); std::cout << "Test EVP_bf_ecb() with 128 bit key: " << printHex(testEVP_bf_ecb(data, key)) << std::endl;
}

This simple test program should print always the same result, but with openSSL 0.9.8o and gcc 4.5.2 output is

From http://www.schneier.com/code/vectors.txt, cipher bytes should be 51866FD5B85ECB8A
Test BF_ecb_encrypt(): 51866FD5B85ECB8A
Test EVP_bf_ecb(): 5AACFB5A8DC0155D
Test EVP_bf_ecb() with 128 bit key: 5AACFB5A8DC0155D

as if EVP_CIPHER_CTX_set_key_length had no effect.
I searched with google if anyone had similar problem, but I found only http://www.mail-archive.com/openssl-users@openssl.org/msg25808.html, and the discussion ends without useful information.
I suspect something in my code being wrong, but I cannot understand what.
Thank you for your help,
Cristiano
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to