Discussion:
Blowfish Encrypt / Decrypt
emyr
2010-10-15 16:23:11 UTC
Permalink
Hi,
After a bit of web research I came up with the program below to try to
get a bowfish function working.
The examples online all seem to be for file stream input rather than for
simple char buffers.
The program fails when I try to decrypt an encrypted buffer and fails on
the EVP_CipherFinal_ex() call.
Anyone able to help me get this working ?
Regards,
Emyr

#include <string.h>

#include <openssl/evp.h>
#include <openssl/buffer.h>

int do_crypt(unsigned char *inbuf, int inlen, unsigned char *outbuf, int
*outlen, int do_encrypt) {
printf("do encrypt=%d\n",do_encrypt);
printf("inlen=%d\n",inlen);
printf("outlen=%d\n",inlen+EVP_MAX_BLOCK_LENGTH);
outbuf=(unsigned char*) malloc(inlen+EVP_MAX_BLOCK_LENGTH);
int tmplen=0;
unsigned char key[] = "0123456789";
unsigned char iv[] = "12345678";
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_CipherInit_ex(&ctx, EVP_bf_cbc(), NULL, NULL, NULL, do_encrypt);
EVP_CIPHER_CTX_set_key_length(&ctx, 10);
EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
if(!EVP_CipherUpdate(&ctx, outbuf, outlen, inbuf, inlen)) {
/* Error */
printf("* update failed *\n");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
int db=*outlen;
printf("db=%d\n",db);
if(!EVP_CipherFinal_ex(&ctx, outbuf+db, &tmplen)) {
/* Error */
printf("* finalise failed *\n");
EVP_CIPHER_CTX_cleanup(&ctx);
return 0;
}
printf("tmplen=%d\n",tmplen);
(*outlen)=db+tmplen;
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}

int main(int argc, char **argv) {
char *plain="the quick brown fox jumps over the lazy dog";
int plain_len=strlen(plain);
printf("plain_len=%d\n",plain_len);
unsigned char *cipher;
int cipher_len;
printf("***** ENCRYPT *****\n");
if (!do_crypt((unsigned char*) plain, strlen(plain), cipher,
&cipher_len, 1)) {
printf("failed to encrypt\n");
return 1;
}
printf("cipher_len=%d\n",cipher_len);
char *decrypt;
int decrypt_len;
printf("***** DECRYPT *****\n");
if(!do_crypt(cipher, cipher_len, decrypt, &decrypt_len, 0)) {
printf("failed to decrypt\n");
return 1;
}
printf("decrypt=\"%s\"\n",decrypt);
printf("decrypt_len=%d\n",decrypt_len);
return 0;
}
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-users-MCmKBN63+***@public.gmane.org
Automated List Manager majordomo-MCmKBN63+***@public.gmane.org
Dave Thompson
2010-10-15 20:16:39 UTC
Permalink
Sent: Friday, 15 October, 2010 12:23
The program fails when I try to decrypt an encrypted buffer
and fails on the EVP_CipherFinal_ex() call.
int do_crypt(unsigned char *inbuf, int inlen,
unsigned char *outbuf, int *outlen, int do_encrypt) {
outbuf=(unsigned char*) malloc(inlen+EVP_MAX_BLOCK_LENGTH);
Asides: you need up to an extra block on CBC *encrypt*.
You don't need extra space on *decrypt*, but it does no harm.

And you don't need to cast the return of malloc if it has been
properly declared by #include'ing <stdlib.h> which it should be;
there are some systems where the C89-default declaration as int()
doesn't work, and on C99 'implicit int' is gone altogether.

<snip: EVP setup, Update>
if(!EVP_CipherFinal_ex(&ctx, outbuf+db, &tmplen)) {
Whenever you get an error from libcrypto routines (and
in most cases libssl routines also) you should display
the OpenSSL error queue. The simplest way is just call
ERR_print_errors_fp(stderr);
after having done SSL_load_error_strings() at startup.
Or there are more customizable options.
int main(int argc, char **argv) {
char *plain="the quick brown fox jumps over the lazy dog";
int plain_len=strlen(plain);
printf("plain_len=%d\n",plain_len);
unsigned char *cipher;
int cipher_len;
printf("***** ENCRYPT *****\n");
if (!do_crypt((unsigned char*) plain, strlen(plain), cipher,
&cipher_len, 1)) {
printf("failed to encrypt\n");
return 1;
}
printf("cipher_len=%d\n",cipher_len);
But this is your problem. You call do_crypt(,,,,1) with an
uninitialized output pointer 'cipher'. do_crypt allocates
the buffer and puts the data there, but 'cipher' in main()
has no idea about this buffer so ...
char *decrypt;
int decrypt_len;
printf("***** DECRYPT *****\n");
if(!do_crypt(cipher, cipher_len, decrypt, &decrypt_len, 0)) {
printf("failed to decrypt\n");
return 1;
}
... this call at best passes garbage to be decrypted,
and could easily even cause SEGV or similar faults.
And similarly even if 'cipher' had been good on that call
'decrypt' wouldn't be for the same reason.

And if decrypt really is char*, the compiler should have required
a cast to unsigned char* there (like for plain in the encrypt call).
printf("decrypt=\"%s\"\n",decrypt);
printf("decrypt_len=%d\n",decrypt_len);
return 0;
See www.c-faq.com number 4.8.



______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-users-MCmKBN63+***@public.gmane.org
Automated List Manager majordomo-MCmKBN63+***@public.gmane.org
emyr
2010-10-18 11:32:40 UTC
Permalink
Hi,

Ah yes... thanks for that Dave. Been doing C++ too much and a bit rusty
on the nuances of pointer stuff...

Anyway, I now have another issue.

What I'm trying to do is to encrypt a password using blowfish, then
base64 it for writing as a string into a config file (it has to be a
plain ascii string - no binary - hence using b64). I then want to read
in the string, UNbase64 it, then decrypt it to recover the correct password.

I found the following...

http://www.ioncannon.net/programming/34/howto-base64-encode-with-cc-and-openssl/
http://www.ioncannon.net/programming/122/howto-base64-decode-with-cc-and-openssl/

which are handy but I don't think this will work as it doesn't tell you
the exact length of the decoded binary buffer - i.e it just uses the
length of the input string which will always be longer than the actual
binary for b64. I will need this for the decrypting to work correctly.
Is it possible to get the exact length of the base64 decoded binary
using the SSL library?

Regards,
Emyr
Post by Dave Thompson
Sent: Friday, 15 October, 2010 12:23
The program fails when I try to decrypt an encrypted buffer
and fails on the EVP_CipherFinal_ex() call.
int do_crypt(unsigned char *inbuf, int inlen,
unsigned char *outbuf, int *outlen, int do_encrypt) {
outbuf=(unsigned char*) malloc(inlen+EVP_MAX_BLOCK_LENGTH);
Asides: you need up to an extra block on CBC *encrypt*.
You don't need extra space on *decrypt*, but it does no harm.
And you don't need to cast the return of malloc if it has been
properly declared by #include'ing<stdlib.h> which it should be;
there are some systems where the C89-default declaration as int()
doesn't work, and on C99 'implicit int' is gone altogether.
<snip: EVP setup, Update>
if(!EVP_CipherFinal_ex(&ctx, outbuf+db,&tmplen)) {
Whenever you get an error from libcrypto routines (and
in most cases libssl routines also) you should display
the OpenSSL error queue. The simplest way is just call
ERR_print_errors_fp(stderr);
after having done SSL_load_error_strings() at startup.
Or there are more customizable options.
int main(int argc, char **argv) {
char *plain="the quick brown fox jumps over the lazy dog";
int plain_len=strlen(plain);
printf("plain_len=%d\n",plain_len);
unsigned char *cipher;
int cipher_len;
printf("***** ENCRYPT *****\n");
if (!do_crypt((unsigned char*) plain, strlen(plain), cipher,
&cipher_len, 1)) {
printf("failed to encrypt\n");
return 1;
}
printf("cipher_len=%d\n",cipher_len);
But this is your problem. You call do_crypt(,,,,1) with an
uninitialized output pointer 'cipher'. do_crypt allocates
the buffer and puts the data there, but 'cipher' in main()
has no idea about this buffer so ...
char *decrypt;
int decrypt_len;
printf("***** DECRYPT *****\n");
if(!do_crypt(cipher, cipher_len, decrypt,&decrypt_len, 0)) {
printf("failed to decrypt\n");
return 1;
}
... this call at best passes garbage to be decrypted,
and could easily even cause SEGV or similar faults.
And similarly even if 'cipher' had been good on that call
'decrypt' wouldn't be for the same reason.
And if decrypt really is char*, the compiler should have required
a cast to unsigned char* there (like for plain in the encrypt call).
printf("decrypt=\"%s\"\n",decrypt);
printf("decrypt_len=%d\n",decrypt_len);
return 0;
See www.c-faq.com number 4.8.
______________________________________________________________________
OpenSSL Project http://www.openssl.org
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-users-MCmKBN63+***@public.gmane.org
Automated List Manager majordomo-MCmKBN63+***@public.gmane.org
Dave Thompson
2010-10-18 23:19:53 UTC
Permalink
Sent: Monday, 18 October, 2010 07:33
Anyway, I now have another issue.
What I'm trying to do is to encrypt a password using blowfish, then
base64 it for writing as a string into a config file [and reverse]
http://www.ioncannon.net/programming/34/howto-base64-encode-wi
th-cc-and-openssl/
http://www.ioncannon.net/programming/122/howto-base64-decode-w
ith-cc-and-openssl/
Those have a lot of unnecessary headers, and are oddly asymmetric:
encode chops the last char, which will always be a newline, but
the decode example has the newline plus a useless null.

Personally I consider it a waste of effort to go through the BIO
structure unless you're streaming, or un/base64ing a whole file
that is conveniently or even better accessed by BIO. When you do,
b64BIO output by default generates and b64BIO input by default
REQUIRES a newline at the end, and intermediate ones depending on
the length of the data. This is correct for the PEM (S/)MIME and
HTTP formats where base64 is most widespread, but often inconvenient
for things like a 'string in a config file', so you may want/need to
BIO_set_flags(b64bio,BIO_FLAGS_BASE64_NO_NL).
which are handy but I don't think this will work as it
doesn't tell you
the exact length of the decoded binary buffer - i.e it just uses the
length of the input string which will always be longer than
the actual
binary for b64. I will need this for the decrypting to work
correctly.
Is it possible to get the exact length of the base64 decoded binary
using the SSL library?
Yes, that code fails to capture the decoded length. Using b64BIO
like that, the number of bytes decoded is the return from BIO_read.
(In general, the return from BIO_read is the data read; for b64BIO,
data read is bytes decoded from chars read from the underlying BIO;
for b64BIO/memBIO-in, it's bytes decoded from chars in the buffer.)

Personally for small in-memory without newlines like this, I just call
EVP_{Encode|Decode}Block. (Or in cases where openssl isn't convenient,
use my own code; it's only about 10 lines to encode and 20 to decode.)



______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-users-MCmKBN63+***@public.gmane.org
Automated List Manager majordomo-MCmKBN63+***@public.gmane.org
Continue reading on narkive:
Loading...