On Thu, Apr 2, 2009 at 10:17 PM, Charles <hobbe...@gmail.com> wrote:
> I posted this before but still haven't solved it:
[...]
> int bf_encrypt( string filename, string msg, string key, string iv ) {
>       unsigned char outbuf[1024];
[...]
>               out.write((char *) &outbuf, outlen );
[...]

Shouldn't need to use an address-of & on an array (~ pointer) var, but
C++ can cope with that.

Either way, doesn't matter: your problem must be elsewhere as I cannot
reproduce your issue (Ubuntu 8.10, OpenSSL 1.1.x CVS HEAD,
size_t-ified).

See attached code; compiled and tested thus:

g...@debbie:~/prj/3actual/openssl$ vi  issue20090405-01.cpp
g...@debbie:~/prj/3actual/openssl$ g++ -c  -m64  -O3 -Wall -Iinclude -o
cpp.o issue20090405-01.cpp
g...@debbie:~/prj/3actual/openssl$ g++ -m64 -Wall -Iinclude -o t  cpp.o
 -L. -lssl -L. -lcrypto  -ldl -lz
g...@debbie:~/prj/3actual/openssl$ ./t 1
Encrypting:
Done!
g...@debbie:~/prj/3actual/openssl$ ./t 2
Decrypting:
Test msg
Done!
g...@debbie:~/prj/3actual/openssl$ od test.bf -t x1
0000000 44 6d 74 af f2 69 99 b0 32 56 af 80 8a c5 80 00
0000020
g...@debbie:~/prj/3actual/openssl$


Given the attached test code, you were saying
  ./t 3
would work for you:
g...@debbie:~/prj/3actual/openssl$ ./t 3
Encrypting:
Decrypting:
Test msg
Done!

(and it does work here), while separate encrypt/decrypt wouldn't:
./t 1
./t 2

which made me curious as code inspection didn't turn up anything
glaringly obvious, nor did this test app, which is just your code in a
simple wrap.


(Note that a few 'int' types in there are 'size_t' in my case, because
I've got a fully size_t-ified OpenSSL source tree over here. However,
a further test with off-the-shelf OpenSSL on a test VM didn't turn up
anything either...)


Are you sure your encrypted data doesn't get b0rked between the
encrypt and decrypt calls somewhere? (Beware that you are using
strings at the plaintext interface level, but encrypted data is just
bytes.)

See the od dump for an encrypted output dump, so you can perform a comparison.


All in all: no problem to be found ;-)
--> bug is to be sought outside the published code, i.e. check your context.


-- 
Met vriendelijke groeten / Best regards,

Ger Hobbelt

--------------------------------------------------
web:    http://www.hobbelt.com/
        http://www.hebbut.net/
mail:   g...@hobbelt.com
mobile: +31-6-11 120 978
--------------------------------------------------
/*
 * help with bad decrypt error?
 *
 * Charles
 * to openssl-users
 *
 * show details Apr 2 (3 days ago)
 *
 *
 *
 *
 * I posted this before but still haven't solved it:
 *
 * I have a function that writes encryption of msg to filename using key
 * and iv.  I have another function that reads filename and decrypts msg
 * using key and iv.  (Source below)
 *
 * If I run my encrypt function to create the encrypted file, and then
 * try and decrypt later with my decrypt function, I get this:
 *  
 * error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad
 * decrypt:evp_enc.c:461:
 *
 * If, however, I run my encrypt and decrypt functions back to back, the
 * decryption works.  I think it's a block length or padding checking
 * problem, but can't figure out why it works sometimes.
 *
 * i.e. this works:
 *
 *
 *
 * bf_encrypt("test.bf", "Test msg", "Test key", "12345678");
 * cout << bf_decrypt("test.bf", "Test key", "12345678") << endl;
 *
 * And this doesn't:
 *
 * bf_encrypt( "test.bf", "Test msg", "Test key","12345678" );
 * cout << bf_decrypt( "test.bf", "Test key","12345678" ) << endl;
 *
 *
 *          Charles
 */


#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/crypto.h>

#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int bf_encrypt(std::string filename, string msg, string key, string iv)
{
	unsigned char outbuf[1024];
	size_t outlen, tmplen;

	EVP_CIPHER_CTX ctx;

	EVP_CIPHER_CTX_init(&ctx);
	EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), NULL, (const unsigned char *)key.c_str(), (const unsigned char *)iv.c_str());

	if (!EVP_EncryptUpdate(&ctx, outbuf, &outlen, (const unsigned char *)msg.c_str(), msg.length()))
	{
		/* Error */
		return 0;
	}

	if (!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen))
	{
		/* Error */
		return 0;
	}
	outlen += tmplen;
	EVP_CIPHER_CTX_cleanup(&ctx);

	ofstream out(filename.c_str(), ios::out | ios::binary);
	if (!out)
	{
		cout << "Cannot open file." << endl;
		return 0;
	}
	else
	{
#if 01
		out.write((char *)&outbuf, outlen);
#else
		out.write((const char *)outbuf, outlen);
#endif
		out.close();
	}

	return 1;
}

std::string bf_decrypt(std::string filename, std::string key, std::string iv)
{
	unsigned char outbuf[1024];
	size_t outlen, tmplen;

	ifstream file(filename.c_str(), ios::in | ios::binary | ios::ate);

	if (file.is_open())
	{
		ifstream::pos_type size;
		char *memblock;
		size = file.tellg();
		memblock = new char[size];
		file.seekg(0, ios::beg);
		file.read(memblock, size);
		file.close();

		EVP_CIPHER_CTX ctx;

		EVP_CIPHER_CTX_init(&ctx);
		EVP_DecryptInit_ex(&ctx, EVP_bf_cbc(), NULL, (const unsigned char *)key.c_str(), (const unsigned char *)iv.c_str());

		if (!EVP_DecryptUpdate(&ctx, outbuf, &outlen, (const unsigned char *)memblock, size))
		{
			cerr << "Error in EVP_DecryptUpdate" << endl;
			return 0;
		}
		if (!EVP_DecryptFinal_ex(&ctx, outbuf + outlen, &tmplen))
		{
			cerr << "Error in EVP_DecryptFinal_ex:" << endl;
			ERR_load_crypto_strings();
			BIO *bo = BIO_new_fp(stdout, BIO_NOCLOSE);
			ERR_print_errors(bo);
			exit(2);
		}
		outlen += tmplen;
		EVP_CIPHER_CTX_cleanup(&ctx);
		delete[] memblock;
		std::string result(reinterpret_cast<const char *>(outbuf), outlen);
		return result;
	}
	else
	{
		cerr << "Unable to open file" << endl;
		return "";
	}
}

int main(int argc, char *argv[])
{
#if 0
    CRYPTO_malloc_debug_init();
    CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

    /* Load up the software EVP_CIPHER and EVP_MD definitions */
    OpenSSL_add_all_ciphers();
    OpenSSL_add_all_digests();
#endif

	int v = atoi(argv[1]);

if (v & 1)
{
cout << "Encrypting:" << endl;
  bf_encrypt("test.bf", "Test msg", "Test key", "12345678");
}
if (v & 2)
{
cout << "Decrypting:" << endl;
  cout << bf_decrypt("test.bf", "Test key", "12345678") << endl;
 }

cout << "Done!" << endl;

#if 0
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
    ERR_remove_thread_state(NULL);
    ERR_free_strings();
    CRYPTO_mem_leaks_fp(stderr);
#endif

    return 0;
}

Reply via email to