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