Hi Support,
I have implemented a demo project at enables encrypting a plaintext based
on 2 input param values.

Version: 1.01f
Cipher Mode: EVP_aes_256_cbc
Salt[]={1,2,3,4,5,6,7,8}
Digest = md5
(functions encapsulated in DLL)

*Encrypt(Param1, Param2, PlainText)* >> Param1 +HardCoded+Param2 =
*Password* >> Password Send to *EVP_BytesToKey* (Salt+Iteration 10) =
Generate Key + IV >> Encrypting PlainText >> Base64Encode to Save in DB

*Decrypt(Param1,Param2,Cipher(ASCII))* >>  Param1 +HardCoded+Param2=
*Password* >>Password Send to *EVP_BytesToKey* (Salt+Iteration 10) =
Generate Key + IV >> Base64Decode >> Decrypt Cipher >>  Output PlainText

i.e:  Encrypt('2', '?this123!', '123456789012') >> QKFf3xNKTgCGghkMziTQQ==

      Decrypt('2', '?this123!', 'QKFf3xNKTgCGghkMziTQQ==') >> 123456789012

Sometimes *Encrypt *resulting an invalid encrypted value or empty result.
it happens randomly on a certain values. As example,

e.g: assumption: instead of 2, we'll pass 3 (guessing 3 is a error prone
param value as described)

Encrypt('3', '?this123!', '123456789012') >> QKiTQ== (this is invalid)

Decrypt('3', '?this123!', 'QKiTQ==') >> ''

I have checked the IV length and its 16. But I changes iteration count,
cipher mode to *EVP_aes_256_ecb (*where IV not considered*)* will gives a
correct output. That even can't guarantee as solution might result an
invalid output on an another value.

Could anybody provide me some solution?

Many Thanks,
Buddhika

PS: I attached a code sample
const static char* b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

const static unsigned char unb64[]={
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //10 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //20 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //30 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //40 
  0,   0,   0,  62,   0,   0,   0,  63,  52,  53, //50 
 54,  55,  56,  57,  58,  59,  60,  61,   0,   0, //60 
  0,   0,   0,   0,   0,   0,   1,   2,   3,   4, //70 
  5,   6,   7,   8,   9,  10,  11,  12,  13,  14, //80 
 15,  16,  17,  18,  19,  20,  21,  22,  23,  24, //90 
 25,   0,   0,   0,   0,   0,   0,  26,  27,  28, //100 
 29,  30,  31,  32,  33,  34,  35,  36,  37,  38, //110 
 39,  40,  41,  42,  43,  44,  45,  46,  47,  48, //120 
 49,  50,  51,   0,   0,   0,   0,   0,   0,   0, //130 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //140 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //150 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //160 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //170 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //180 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //190 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //200 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //210 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //220 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //230 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //240 
  0,   0,   0,   0,   0,   0,   0,   0,   0,   0, //250 
  0,   0,   0,   0,   0,   0, 
};


/*----------------------------------------------------------------------------*/
/* do convert binary to plaintext and vice versa using base 64 encode/decode  */
/*----------------------------------------------------------------------------*/
char* convert_to_base64(const void* binaryData, int len, int *flen )
{ 
  const unsigned char* bin = (const unsigned char*) binaryData ;
  char* res ;
  
  int rc = 0; // result counter
  int byteNo; // I need this after the loop
  
  int modulusLen = len % 3 ;
  int pad = ((modulusLen&1)<<1) + ((modulusLen&2)>>1) ; // 2 gives 1 and 1 gives 2, but 0 gives 0.
  
  *flen = 4*(len + pad)/3 ;
  res = (char*) malloc( *flen + 1 ) ; // and one for the null
  
	if( !res ){
		return 0;
  }  
  // encoding...
  for( byteNo = 0 ; byteNo <= len-3 ; byteNo+=3 ){
    unsigned char BYTE0=bin[byteNo];
    unsigned char BYTE1=bin[byteNo+1];
    unsigned char BYTE2=bin[byteNo+2];
    res[rc++]  = b64[BYTE0 >> 2];
    res[rc++]  = b64[((0x3&BYTE0)<<4)  + (BYTE1 >> 4)];
    res[rc++]  = b64[((0x0f&BYTE1)<<2) + (BYTE2>>6)  ];
    res[rc++]  = b64[0x3f&BYTE2];
  }
  // pad level 2
  if( pad==2 ){
    res[rc++] = b64[bin[byteNo] >> 2];
    res[rc++] = b64[(0x3&bin[byteNo])<<4];
    res[rc++] = '=';
    res[rc++] = '=';
  }
	// pad level 1
  else if( pad==1 ){
    res[rc++]  = b64[bin[byteNo] >> 2] ;
    res[rc++]  = b64[((0x3&bin[byteNo])<<4) + (bin[byteNo+1] >> 4)];
    res[rc++]  = b64[(0x0f&bin[byteNo+1])<<2];
    res[rc++] = '=';
  }  
  res[rc]=0; // null terminate
  return res;
}
/*----------------------------------------------------------------------------*/
unsigned char* convert_from_base64(const char *encodedStr, int len, int *flen )
{
  const unsigned char *safePtr = (const unsigned char*)encodedStr;
  unsigned char *bin;
  int cb=0,pad=0;
  int charNo;

  // catch empty/invalid encoded string, return NULL as result.
  if( len < 2 ) {
    *flen=0;
    return 0 ;
  }
  
	if( safePtr[len-1]=='=') ++pad;
  if( safePtr[len-2]=='=') ++pad;
  
  *flen = 3*len/4 - pad;
  bin = (unsigned char*)malloc( *flen ) ;

	// not enough memory to continue. exisiting...
  if(!bin){
    return 0;
  }

  // decoding...
  for( charNo=0; charNo <= len - 4 - pad ; charNo+=4 ){
    int A=unb64[safePtr[charNo  ]];
    int B=unb64[safePtr[charNo+1]];
    int C=unb64[safePtr[charNo+2]];
    int D=unb64[safePtr[charNo+3]];
    
    bin[cb++] = (A<<2) | (B>>4);
    bin[cb++] = (B<<4) | (C>>2);
    bin[cb++] = (C<<6) | (D);
  }
  // calling pad level 1
  if( pad==1 ){
    int A=unb64[safePtr[charNo  ]];
    int B=unb64[safePtr[charNo+1]];
    int C=unb64[safePtr[charNo+2]];
    
    bin[cb++] = (A<<2) | (B>>4) ;
    bin[cb++] = (B<<4) | (C>>2) ;
  }
	// calling pad level 2
  else if( pad==2 )
  {
    int A=unb64[safePtr[charNo  ]];
    int B=unb64[safePtr[charNo+1]];
    
    bin[cb++] = (A<<2) | (B>>4) ;
  }  
  return bin ;
}
/*----------------------------------------------------------------------------*/
/* set character pattern + encryption/decryption using OpenSSL EVP AES 256    */
/*----------------------------------------------------------------------------*/
void set_pattern(unsigned char* rz,unsigned char* seq)
{
	// uses 3rd variable to generate final char pattern
  strcat(rz,"Concat");
	strcat(rz,seq);
}
/*----------------------------------------------------------------------------*/
short int do_encrypt(const char *data, unsigned char *out, int *outlen, unsigned char *key, unsigned char *iv)
{
  int buflen, tmplen;
  // init cipher context
  EVP_CIPHER_CTX ctx;
  EVP_CIPHER_CTX_init(&ctx);
  EVP_EncryptInit_ex(&ctx, MY_CIPHER_MODE, NULL, key, iv);
  // encrypt data
  if(!EVP_EncryptUpdate(&ctx, out, &buflen, (unsigned char*)data, strlen(data)))  {
        return 0;
  }
  if(!EVP_EncryptFinal_ex(&ctx, out + buflen, &tmplen))  {
        return 0;
  }    
  buflen += tmplen;
  *outlen = buflen;
	// clean
  EVP_CIPHER_CTX_cleanup(&ctx);

  return 1;
}
/*----------------------------------------------------------------------------*/
short int do_decrypt(const unsigned char *cipher, unsigned char *out, unsigned char *key, unsigned char *iv)
{
  int buflen, tmplen, outlen;
	// init cipher context
  EVP_CIPHER_CTX ctx;
  EVP_CIPHER_CTX_init(&ctx);
  EVP_DecryptInit_ex(&ctx, MY_CIPHER_MODE, NULL, key, iv);
  // decrypt data  
  if(!EVP_DecryptUpdate(&ctx, out, &buflen, cipher, strlen(cipher))) {
    return 0;
  }  
  if(!EVP_DecryptFinal_ex(&ctx, out + buflen, &tmplen)) {
    return 0;
  } 
  outlen = buflen + tmplen;
  out[outlen] =(char) 0;  
	// clean
  EVP_CIPHER_CTX_cleanup(&ctx);

  return 1;
}
/*----------------------------------------------------------------------------*/
/* PNA_DLL_EXPORT external entry points: EncodeData/DecodeData/ReEncodeData   */
/*----------------------------------------------------------------------------*/
DLL_EXPORT unsigned char* Encrypt(unsigned char *seq_1,	unsigned char *seq_2 , unsigned char *data)
{
	if (data==NULL){
	  return NULL;
	}else {
		const EVP_MD *dgst;
		unsigned char salt[]= {1,2,3,4,5,6,7,8};
		unsigned int outlen,x;
		unsigned char *sz_result=(unsigned char*)MALLOC(LOC_STRING_SIZE);   // have used this with firebird ib_utils  lib

		unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
		unsigned char cipher[LOC_STRING_SIZE],sz_code[LOC_STRING_SIZE] ;
		memset(key		, 0, sizeof(key    ));
		memset(iv			, 0, sizeof(iv		 ));
		memset(cipher , 0, sizeof(cipher ));
		memset(sz_code, 0, sizeof(sz_code));
		
		// load all algos + set digest to md5
		OpenSSL_add_all_algorithms();
		dgst=EVP_get_digestbyname("md5");
		// set pattern
		strcpy(sz_code,seq_1); 
		set_pattern(sz_code,seq_2); 
		// generate key and iv
		if (!EVP_BytesToKey(MY_CIPHER_MODE,dgst,salt,sz_code,strlen(sz_code),10,key,iv)){
			sprintf(sz_result,"%s","KEY GENERATE ERROR!!!");
		}else {
			// if key success, then to encrypt the data
			if (!do_encrypt((char*)data, cipher, &outlen, key, iv)){
				sprintf(sz_result,"%s","ENCRYPTION ERROR!!!");	
			}else {
				sprintf(sz_result,"%s",(convert_to_base64(cipher,strlen(cipher),&x)));
				//sprintf(sz_result,"%d",strlen(iv));
			}
		}
		return sz_result;
	}
}
/*----------------------------------------------------------------------------*/
DLL_EXPORT unsigned char* Decrypt(unsigned char *seq_1,	unsigned char *seq_2, unsigned char *cipher)
{	
	if (cipher==NULL){
	  return NULL;
	}else {
		const EVP_MD *dgst;
		unsigned int x;
		unsigned char salt[]= {1,2,3,4,5,6,7,8};
		unsigned char *sz_result=(unsigned char*)MALLOC(LOC_STRING_SIZE);

		unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
		unsigned char plainText[LOC_STRING_SIZE],sz_code[LOC_STRING_SIZE] ;	
		memset(key		   , 0, sizeof(key      ));
		memset(iv			   , 0, sizeof(iv		    ));
		memset(plainText , 0, sizeof(plainText));
		memset(sz_code   , 0, sizeof(sz_code  ));

		// loading all algorithems and set digest to md5
		OpenSSL_add_all_algorithms();	
		dgst   =EVP_get_digestbyname("md5");
		// set pattern
		strcpy(sz_code,seq_1); 
		set_pattern(sz_code,seq_2);  
		//generate key + iv >> KEY should identical to original encrypted key
		if (!EVP_BytesToKey(MY_CIPHER_MODE,dgst,salt,sz_code,strlen(sz_code),10,key,iv)){
			sprintf(sz_result,"%s","KEY GENERATE ERROR!!!");
		}else {
			// if key success, then to decrypt 
			do_decrypt((convert_from_base64((char*)cipher,strlen(cipher),&x)), plainText, key, iv);
			sprintf(sz_result,"%s",plainText);
		}
		return sz_result;
	}
}

Reply via email to