Hello.
I'm trying to write a simple C program to encrypt a password using
Blowfish and then Base64 encode it, and another to do the opposite,
decode then decrypt.
I'm using EVP_Encrypt*()/EVP_Decrypt*() for Blowfish and I've already
tried EVP_Encode*()/EVP_Decode*() and BIO_*(). For encryption, both ways
seemed to work the same way. For decryption, none work always.
I've attached the source of the EVP_Encode*() encrypting program and
also both of the decrypting sources. If you'd like to test them, try to
encode the string "tico eh o cachorro do be" and "Sei la". Each one
works well for only one of the decrypting codes.
Thanks anyway,
Eduardo
--------------2BC44B917DD3C1EA57A98E99
Content-Type: text/plain; charset=us-ascii;
name="crypt2.c"
Content-Disposition: inline;
filename="crypt2.c"
Content-Transfer-Encoding: 7bit
/*
* Reads a string, encrypts it using Blowfish and writes it to disk encoded
* with base64.
* Working well.
*/
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
int main(int argc, char* argv[]) {
/* Variables */
char *ascbuf = argv[1];
unsigned char bfbuf[1024];
unsigned char b64buf[1024];
unsigned char *newbuf;
FILE *out;
char *outfile = argv[2];
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,65,13,14,15};
unsigned char iv[] = {1,2,3,4,5,6,7,8};
EVP_CIPHER_CTX ctx;
int outlen, tmplen;
/* EVP_Encode*() Base64 */
EVP_ENCODE_CTX ectx;
int len, total = 0;
/* Usage */
if(argc != 3) {
printf("Usage: crypt \"String to encrypt\" output.filename\n");
return 0;
}
printf("\nYour string: %s", ascbuf);
/* Bluefish encryption using EVP (www.openssl.org/docs/crypto/evp.html#) */
//EVP_EncryptInit(&ctx, EVP_des_cbc(), key, iv);
printf("\nEncrypting string...");
//EVP_EncryptInit(&ctx, EVP_des_cbc(), key, iv);
EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
if(!EVP_EncryptUpdate(&ctx, bfbuf, &outlen, ascbuf, strlen(ascbuf))) {
return 0;
}
if(!EVP_EncryptFinal(&ctx, bfbuf + outlen, &tmplen)) {
return 0;
}
outlen += tmplen;
//printf("\nEncrypted string: %s", bfbuf);
/* Base64 using EVP */
printf("\nEncoding string...");
EVP_EncodeInit(&ectx);
EVP_EncodeUpdate(&ectx, b64buf, &len, bfbuf, outlen);
total += len;
EVP_EncodeFinal(&ectx, b64buf, &len);
total += len;
printf("\nBase64 encoded string: %s\n",b64buf);
/* Writes to disk */
out = fopen(outfile, "wb");
fwrite(b64buf,1,total,out);
fclose(out);
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}
--------------2BC44B917DD3C1EA57A98E99
Content-Type: text/plain; charset=us-ascii;
name="decrypt.c"
Content-Disposition: inline;
filename="decrypt.c"
Content-Transfer-Encoding: 7bit
/*
* Decodes a Base64 encoded string, Blowfish decrypts it, and puts it on the
* screen.
* EVP_DecryptFinal() still fails when password is too big.
*/
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
int main(int argc, char* argv[]) {
/* Variables */
char *infile = argv[1];
FILE *in;
/* base64 string, encrypted string, pure text string */
unsigned char inbuf[1024];
unsigned char bfbuf[1024];
char ascbuf[1024];
/* EVP_Decrypt*() */
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,65,13,14,15};
unsigned char iv[] = {1,2,3,4,5,6,7,8};
EVP_CIPHER_CTX ctx;
int outlen, tmplen;
/* Base64 BIO decode */
BIO *mbio, *bio, *b64;
/* Usage */
if(argc != 2) {
printf("Usage: decrypt input.filename\n");
return 0;
}
/* Opens infile and reads a string from it */
in = fopen(infile, "rb");
fgets(inbuf, 1024, in);
fclose(in);
printf("\nBase64 encoded string: %s", inbuf);
/* Base64 */
printf("\nDecoding string...");
mbio = BIO_new(BIO_s_mem());
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, mbio);
/* Writes string to memory BIO */
BIO_write(mbio, inbuf, strlen(inbuf));
/* Reads/decrypts string in memory BIO */
BIO_read(bio, bfbuf, 1024);
/* Do not print this string, it may scramble your terminal */
//printf("Base64 decoded string \(Blowfish encrypted\): %s\n", bfbuf);
BIO_free_all(bio);
/* Bluefish decryption using EVP (www.openssl.org/docs/crypto/evp.html#) */
printf("\nDecrypting string...");
EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
if(!EVP_DecryptUpdate(&ctx, ascbuf, &outlen, bfbuf, strlen(bfbuf))) {
return 0;
}
if(!EVP_DecryptFinal(&ctx, ascbuf + outlen, &tmplen)) {
printf("DecryptFinal failed.\n");
//return 0;
}
EVP_CIPHER_CTX_cleanup(&ctx);
printf("Decrypted string: %s\n\n", ascbuf);
return 1;
}
--------------2BC44B917DD3C1EA57A98E99
Content-Type: text/plain; charset=us-ascii;
name="decrypt2.c"
Content-Disposition: inline;
filename="decrypt2.c"
Content-Transfer-Encoding: 7bit
/*
* Decodes a Base64 encoded string, Blowfish decrypts it, and puts it on the
* screen.
* EVP_DecryptFinal() still fails when password is too big.
*/
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
int main(int argc, char* argv[]) {
/* Variables */
char *infile = argv[1];
FILE *in;
/* base64 string, encrypted string, pure text string */
unsigned char inbuf[1024];
unsigned char bfbuf[1024];
char ascbuf[1024];
/* EVP_Decrypt*() */
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,65,13,14,15};
unsigned char iv[] = {1,2,3,4,5,6,7,8};
EVP_CIPHER_CTX ctx;
int outlen, tmplen;
/* Base64 EVP_Decode*() */
EVP_ENCODE_CTX ectx;
int len, total = 0;
/* Usage */
if(argc != 2) {
printf("Usage: decrypt input.filename\n");
return 0;
}
/* Opens infile and reads a string from it */
in = fopen(infile, "rb");
fgets(inbuf, 1024, in);
fclose(in);
printf("\nBase64 encoded string: %s", inbuf);
/* Base64 decodification */
printf("\nDecoding string...");
EVP_DecodeInit(&ectx);
EVP_DecodeUpdate(&ectx, bfbuf, &len, inbuf, strlen(inbuf));
total += len;
EVP_DecodeFinal(&ectx, bfbuf, &len);
total += len;
//printf("total = %d\n", total);
/* Decryption using EVP (www.openssl.org/docs/crypto/evp.html#) */
printf("\nDecrypting string...");
//EVP_DecryptInit(&ctx, EVP_des_cbc(), key, iv);
EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
if(!EVP_DecryptUpdate(&ctx, ascbuf, &outlen, bfbuf, total)) {
return 0;
}
if(!EVP_DecryptFinal(&ctx, ascbuf + outlen, &tmplen)) {
// EVP_DecryptFinal() still fail when password is too big.
printf("DecryptFinal failed.\n");
//return 0;
}
EVP_CIPHER_CTX_cleanup(&ctx);
printf("\nDecrypted string: %s\n\n", ascbuf);
return 1;
}
--------------2BC44B917DD3C1EA57A98E99--
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org
EVP_EncodeFinal(&ectx, b64buf + len, &len);
instead of
EVP_EncodeFinal(&ectx, b64buf, &len);
and similarly for EVP_DecodeFinal. It probably only works when the length of
ascbuf is 0 mod 4.
====================
Greg Stark
ghs...@pobox.com
====================
----- Original Message -----
From: "Eduardo Sztokbant" <edu...@registro.br>
To: <openss...@openssl.org>
Sent: Monday, June 25, 2001 2:08 PM
Subject: Blowfish encrypting + Base64 encoding
> Hello.
>
> I'm trying to write a simple C program to encrypt a password using
> Blowfish and then Base64 encode it, and another to do the opposite,
> decode then decrypt.
>
> I'm using EVP_Encrypt*()/EVP_Decrypt*() for Blowfish and I've already
> tried EVP_Encode*()/EVP_Decode*() and BIO_*(). For encryption, both ways
> seemed to work the same way. For decryption, none work always.
>
> I've attached the source of the EVP_Encode*() encrypting program and
> also both of the decrypting sources. If you'd like to test them, try to
> encode the string "tico eh o cachorro do be" and "Sei la". Each one
> works well for only one of the decrypting codes.
>
> Thanks anyway,
> Eduardo
----------------------------------------------------------------------------
----
> file://EVP_EncryptInit(&ctx, EVP_des_cbc(), key, iv);
> printf("\nEncrypting string...");
> file://EVP_EncryptInit(&ctx, EVP_des_cbc(), key, iv);
> EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
> if(!EVP_EncryptUpdate(&ctx, bfbuf, &outlen, ascbuf, strlen(ascbuf))) {
> return 0;
> }
> if(!EVP_EncryptFinal(&ctx, bfbuf + outlen, &tmplen)) {
> return 0;
> }
>
> outlen += tmplen;
>
> file://printf("\nEncrypted string: %s", bfbuf);
>
> /* Base64 using EVP */
> printf("\nEncoding string...");
> EVP_EncodeInit(&ectx);
> EVP_EncodeUpdate(&ectx, b64buf, &len, bfbuf, outlen);
> total += len;
> EVP_EncodeFinal(&ectx, b64buf, &len);
> total += len;
>
> printf("\nBase64 encoded string: %s\n",b64buf);
>
> /* Writes to disk */
> out = fopen(outfile, "wb");
> fwrite(b64buf,1,total,out);
> fclose(out);
>
> EVP_CIPHER_CTX_cleanup(&ctx);
>
> return 1;
> }
>
----------------------------------------------------------------------------
----
> file://printf("Base64 decoded string \(Blowfish encrypted\): %s\n",
bfbuf);
>
> BIO_free_all(bio);
>
> /* Bluefish decryption using EVP (www.openssl.org/docs/crypto/evp.html#)
*/
> printf("\nDecrypting string...");
> EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
> if(!EVP_DecryptUpdate(&ctx, ascbuf, &outlen, bfbuf, strlen(bfbuf))) {
> return 0;
> }
> if(!EVP_DecryptFinal(&ctx, ascbuf + outlen, &tmplen)) {
> printf("DecryptFinal failed.\n");
> file://return 0;
> }
>
> EVP_CIPHER_CTX_cleanup(&ctx);
>
> printf("Decrypted string: %s\n\n", ascbuf);
>
> return 1;
> }
>
----------------------------------------------------------------------------
----
> file://printf("total = %d\n", total);
>
> /* Decryption using EVP (www.openssl.org/docs/crypto/evp.html#) */
> printf("\nDecrypting string...");
> file://EVP_DecryptInit(&ctx, EVP_des_cbc(), key, iv);
> EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
> if(!EVP_DecryptUpdate(&ctx, ascbuf, &outlen, bfbuf, total)) {
> return 0;
> }
> if(!EVP_DecryptFinal(&ctx, ascbuf + outlen, &tmplen)) {
> // EVP_DecryptFinal() still fail when password is too big.
> printf("DecryptFinal failed.\n");
> file://return 0;
> }
>
> EVP_CIPHER_CTX_cleanup(&ctx);
>
> printf("\nDecrypted string: %s\n\n", ascbuf);
>
> return 1;
> }
>
>
______________________________________________________________________
Thank you, Greg! Your hint and another friend's one helped me a lot. My
friend's idea was to run "bzero" on the buffers before
decoding/decrypting, which seems to be necessary.
I corrected the bugs on crypt2.c/decrypt2.c and also started developing
a C++ class named "Senha" that handles the functionality in
crypt/decrypt and can be useful for other programmers. The class is
still poorly implemented (I've worked on it for less than tree hours)
but it is potentially useful and is already working. If anybody wants to
help me working on it, I'll be very grateful.
All those files are attached with this message.
Bye for now,
Eduardo Sztokbant (edu...@registro.br)
Greg Stark wrote:
>
> I think your second argument to EVP_EncodeFinal() and EVP_DecodeFinal() is
> buggy, e.g. I suspect it should be:
>
> EVP_EncodeFinal(&ectx, b64buf + len, &len);
>
> instead of
>
> EVP_EncodeFinal(&ectx, b64buf, &len);
>
> and similarly for EVP_DecodeFinal. It probably only works when the length of
> ascbuf is 0 mod 4.
>
> ====================
> Greg Stark
> ghs...@pobox.com
> ====================
--------------DE5B41C1C8F08B38F1110F0F
Content-Type: text/plain; charset=us-ascii;
name="crypt2.c"
Content-Disposition: inline;
filename="crypt2.c"
Content-Transfer-Encoding: 7bit
/*
* Reads a string, encrypts it using Blowfish and writes it to disk encoded
* with base64.
* by Eduardo Sztokbant (edu...@registro.br) - Jun/2001
* Thanks for those who invented open source and free software!
//EVP_EncryptInit(&ctx, EVP_des_cbc(), key, iv);
printf("\nEncrypting string...");
//EVP_EncryptInit(&ctx, EVP_des_cbc(), key, iv);
EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
if(!EVP_EncryptUpdate(&ctx, bfbuf, &outlen, ascbuf, strlen(ascbuf))) {
return 0;
}
if(!EVP_EncryptFinal(&ctx, bfbuf + outlen, &tmplen)) {
return 0;
}
outlen += tmplen;
//printf("\nEncrypted string: %s", bfbuf);
/* Base64 using EVP */
printf("\nEncoding string...");
EVP_EncodeInit(&ectx);
EVP_EncodeUpdate(&ectx, b64buf, &len, bfbuf, outlen);
total += len;
EVP_EncodeFinal(&ectx, b64buf + len, &len);
total += len;
printf("\nBase64 encoded string: %s\n",b64buf);
/* Writes to disk */
out = fopen(outfile, "wb");
fwrite(b64buf,1,total,out);
fclose(out);
EVP_CIPHER_CTX_cleanup(&ctx);
return 1;
}
--------------DE5B41C1C8F08B38F1110F0F
Content-Type: text/plain; charset=us-ascii;
name="decrypt2.c"
Content-Disposition: inline;
filename="decrypt2.c"
Content-Transfer-Encoding: 7bit
/*
* Decodes a Base64 encoded string, Blowfish decrypts it, and puts it on the
* screen.
* by Eduardo Sztokbant (edu...@registro.br)
* Thanks for those who invented open source and free software!
*/
#include <stdio.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
int main(int argc, char* argv[]) {
/* Variables */
char *infile = argv[1];
FILE *in;
/* base64 string, encrypted string, pure text string */
unsigned char inbuf[1024];
unsigned char bfbuf[1024];
char ascbuf[1024];
/* EVP_Decrypt*() */
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,65,13,14,15};
unsigned char iv[] = {1,2,3,4,5,6,7,8};
EVP_CIPHER_CTX ctx;
int outlen, tmplen;
/* Base64 EVP_Decode*() */
EVP_ENCODE_CTX ectx;
int len, total = 0;
/* Usage */
if(argc != 2) {
printf("Usage: decrypt input.filename\n");
return 0;
}
/* Resets all buffers */
bzero(inbuf,1024);
bzero(bfbuf,1024);
bzero(ascbuf,1024);
/* Opens infile and reads a string from it */
in = fopen(infile, "rb");
//fgets(inbuf, 1024, in);
fread(inbuf,1024,1,in);
fclose(in);
printf("\nBase64 encoded string: %s", inbuf);
/* Base64 decodification */
printf("\nDecoding string...");
EVP_DecodeInit(&ectx);
EVP_DecodeUpdate(&ectx, bfbuf, &len, inbuf, strlen(inbuf));
total += len;
EVP_DecodeFinal(&ectx, bfbuf + len, &len);
total += len;
/* Decryption using EVP (www.openssl.org/docs/crypto/evp.html#) */
printf("\nDecrypting string...");
EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
if(!EVP_DecryptUpdate(&ctx, ascbuf, &outlen, bfbuf, total)) {
return 0;
}
if(!EVP_DecryptFinal(&ctx, ascbuf + outlen, &tmplen)) {
printf("DecryptFinal failed.\n");
//return 0;
}
EVP_CIPHER_CTX_cleanup(&ctx);
printf("\nDecrypted string: (%s)\n\n", ascbuf);
return 1;
}
--------------DE5B41C1C8F08B38F1110F0F
Content-Type: text/plain; charset=us-ascii;
name="senha.h"
Content-Disposition: inline;
filename="senha.h"
Content-Transfer-Encoding: 7bit
/*
* This class was made to handle encrypted/encoded passwords.
* by Eduardo Sztokbant (edu...@registro.br) - Jun/2001
* Thanks for those who invented open source and free software!
*/
#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
// Stores a Blowfish encrypted string, Base64 encoded
class Senha {
unsigned char b64buf[1024];
unsigned char key[16];
unsigned char iv[8];
int encrypt(char *ascbuf, unsigned char iv[8], unsigned char key[16], unsigned char *bfbuf);
int encode(unsigned char *bfbuf, int outlen);
int decode(unsigned char *bfbuf);
int decrypt(unsigned char *bfbuf, int total, char *ascbuf);
void setkey(unsigned char key[16]);
void setiv(unsigned char iv[8]);
public:
Senha(unsigned char key[16], unsigned char iv[8], char *ascbuf);
unsigned char * getbuf(void);
char * retrieve(unsigned char key[16], unsigned char iv[8]);
bool change(unsigned char key[16], unsigned char iv[8], char *newbuf);
};
// Constructor
Senha::Senha(unsigned char key[16], unsigned char iv[8], char *ascbuf) {
int outlen;
int total;
unsigned char bfbuf[1024];
Senha::setkey(key);
Senha::setiv(iv);
outlen = Senha::encrypt(ascbuf, this->iv, this->key, bfbuf);
total = Senha::encode(bfbuf, outlen);
}
// Returns buffer b64buf
unsigned char * Senha::getbuf(void) {
return this->b64buf;
}
// Blowfish encrypts ascbuf into bfbuf
int Senha::encrypt(char *ascbuf, unsigned char iv[8], unsigned char key[16], unsigned char *bfbuf) {
EVP_CIPHER_CTX ctx;
int outlen, tmplen;
EVP_EncryptInit(&ctx, EVP_bf_cbc(), key, iv);
if(!EVP_EncryptUpdate(&ctx, bfbuf, &outlen, (unsigned char *)ascbuf, strlen(ascbuf))) {
return 0;
}
if(!EVP_EncryptFinal(&ctx, bfbuf + outlen, &tmplen)) {
return 0;
}
outlen += tmplen;
return outlen;
}
// Base64 encodes bfbuf into b64buf
int Senha::encode(unsigned char *bfbuf, int outlen) {
EVP_ENCODE_CTX ectx;
int len, total = 0;
EVP_EncodeInit(&ectx);
EVP_EncodeUpdate(&ectx, this->b64buf, &len, bfbuf, outlen);
total += len;
EVP_EncodeFinal(&ectx, this->b64buf, &len);
total += len;
return total;
}
// Sets the key
void Senha::setkey(unsigned char key[16]) {
for(int i=0; i<16; ++i) {
this->key[i] = key[i];
}
}
// Sets the iv
void Senha::setiv(unsigned char iv[8]) {
for(int i=0; i<8; ++i) {
this->iv[i] = iv[i];
}
}
// Returns plain text decoded string
char * Senha::retrieve(unsigned char key[16], unsigned char iv[8]) {
/* base64 string, encrypted string, pure text string */
unsigned char bfbuf[1024];
char ascbuf[1024];
/* Resets all buffers (necessary, otherwise it will not work always) */
bzero(bfbuf,1024);
bzero(ascbuf,1024);
int total = decode(bfbuf);
int outlen = decrypt(bfbuf, total, ascbuf);
return ascbuf;
}
/* Base64 decodification */
int Senha::decode(unsigned char *bfbuf) {
EVP_ENCODE_CTX ectx;
int len, total = 0;
EVP_DecodeInit(&ectx);
EVP_DecodeUpdate(&ectx, bfbuf, &len, this->b64buf, strlen((const char *)this->b64buf));
total += len;
EVP_DecodeFinal(&ectx, bfbuf + len, &len);
total += len;
return total;
}
// Blowfish decryption
int Senha::decrypt(unsigned char *bfbuf, int total, char *ascbuf) {
EVP_CIPHER_CTX ctx;
int outlen, tmplen;
EVP_DecryptInit(&ctx, EVP_bf_cbc(), key, iv);
if(!EVP_DecryptUpdate(&ctx, (unsigned char *)ascbuf, &outlen, bfbuf, total)) {
return 0;
}
if(!EVP_DecryptFinal(&ctx, (unsigned char *)ascbuf + outlen, &tmplen)) {
//printf("DecryptFinal failed.\n");
return 0;
}
EVP_CIPHER_CTX_cleanup(&ctx);
return outlen;
}
// Verifyes the key and changes the password
bool Senha::change(unsigned char key[16], unsigned char iv[8], char *newbuf) {
bool value = true;
for(int i=0; i<8; i++) {
if(iv[i] != this->iv[i]) value = false;
}
for(int i=0; i<16; i++) {
if(key[i] != this->key[i]) value = false;
}
if(value) {
int outlen;
int total;
unsigned char bfbuf[1024];
outlen = Senha::encrypt(newbuf, this->iv, this->key, bfbuf);
total = Senha::encode(bfbuf, outlen);
}
return value;
}
--------------DE5B41C1C8F08B38F1110F0F--