Error CryptDecode

 

Hi,

just trying the new CryptEncode and CryptDecode functions. Everything is working as expected with CryptEncode. However when using the provided example with a slight modification (converting the char array into a string and back to a char array). I am getting the 4029 error.

//+------------------------------------------------------------------+
//| ArrayToHex                                                       |
//+------------------------------------------------------------------+
string ArrayToHex(uchar &arr[],int count=-1)
  {
   string res="";
//--- check
   if(count<0 || count>ArraySize(arr))
      count=ArraySize(arr);
//--- transform to HEX string
   for(int i=0; i<count; i++)
      res+=StringFormat("%.2X",arr[i]);
//---
   return(res);
  }
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   string text="The quick brown fox jumps over the lazy dog";
   string keystr="ABCDEFG";
   uchar src[],dst[],key[];
//--- prepare key
   StringToCharArray(keystr,key);
//--- copy text to source array src[]
   StringToCharArray(text,src);
//--- print initial data
   PrintFormat("Initial data: size=%d, string='%s'",ArraySize(src),CharArrayToString(src));
//--- encrypt src[] with DES 56-bit key in key[]
   int res=CryptEncode(CRYPT_DES,src,key,dst);
//--- check error
   if(res>0)
     {
      //--- print encrypted data
      PrintFormat("Encoded data: size=%d %s",res,ArrayToHex(dst));
      //--- decode dst[] to src[]

//modifications
string dstStr = CharArrayToString(dst);
uchar dst2[],src2[];
StringToCharArray(dstStr,dst2);
res=CryptDecode(CRYPT_DES,dst2,key,src2);
// end modifications

      //--- check error     
      if(res>0)
        {
         //--- print decoded data
         PrintFormat("Decoded data: size=%d, string='%s'",ArraySize(src),CharArrayToString(src));
        }
      else
         Print("Error in CryptDecode. Error code=",GetLastError());
     }
   else
      Print("Error in CryptEncode. Error code=",GetLastError());
  }
 
what's the purpose of doing this
 

this obviously has no purpose. It's just for showing the error :)

In the real application I am trying to convert a base64encoded string which is resulting in the same error. In order to decode this string I have to map it to a chararray because CryptDecode only accepts an uchar array as parameter.

 

then use

res=CryptDecode(CRYPT_BASE64,dst,key,src);

why all the trouble to convert from CharArrayToString and convert back StringToCharArray

it's the like you were doing:

int a = 10 * 10;
int b = a / 10;
 

ok ... I didn't make myself clear probably. So another example which hopefully shows my problem better.

string textBase64="VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="; //The quick brown fox jumps over the lazy dog
string keystr="ABCDEFG";
   
uchar src[],dst[],key[];
//--- prepare key
StringToCharArray(keystr,key);
//--- copy text to source array src[]
StringToCharArray(textBase64,src);

//--- decrypt src[] with base64 key in key[]
int res=CryptDecode(CRYPT_BASE64,src,key,dst);
//--- check error
   if(res>0)
   {
      //--- print decrypted data
      Print(StringConcatenate("Decoded data: ",CharArrayToString(dst)));
   }
   else
      Print("Error in CryptDecode. Error code=",GetLastError());   
 

you have to remove the last char from the string after converting from CharArrayToString

//modifications
string dstStr = CharArrayToString(dst);
string dstStrTrimmed = StringSubstr(dstStr, 0, StringLen(dstStr) -1);
uchar dst2[],src2[];
StringToCharArray(dstStrTrimmed,dst2);
res=CryptDecode(CRYPT_DES,dst2,key,src2);
// end modifications
 

Thank you so much! This is working perfectly for CRYPT_DES or CRYPT_BASE64.

How about CRYPT_AES128 or CRYPT_AES256. There I am still getting the 4029 error. Do you have a hint on that one also? :)

 

Sorry gjol ... your solution is also working for CRYPT_AES128+. I just forgot to adapt the key. Need to use a 32 long keystring.

Thanks again foir your help! 

 

ok ... me again. Was a little quick with reporting success ;)

The result of the workaround provided by gjol is totally different depending on the used coding method.

- It is working with CRYPT_BASE64
- with CRYPT_AES128 I am still getting the 4029 error
- with CRYPT_DES or CRYPT_AES256 the 4029 error is gone ... however the result is not as expected. See below (using CRYPT_AES256):

   string text="The quick brown fox jumps over the lazy dog";
   string keystr="9ADE769DE7B2D51F6EBBC3CC7F744ZY5";

   uchar src[],dst[],key[];
//--- prepare key
   StringToCharArray(keystr,key);
//--- copy text to source array src[]
   StringToCharArray(text,src);
//--- print initial data
   PrintFormat("Initial data: size=%d, string='%s'",ArraySize(src),CharArrayToString(src));
//--- encrypt src[] with DES 56-bit key in key[]
   int res=CryptEncode(CRYPT_AES256,src,key,dst);
//--- check error
   if(res>0)
     {
      //--- print encrypted data
      PrintFormat("Encoded data: size=%d %s",res,ArrayToHex(dst));
      //--- decode dst[] to src[]

//modifications
string dstStr = CharArrayToString(dst);
uchar dst2[],src2[];
StringToCharArray(StringSubstr(dstStr,0,StringLen(dstStr)-1),dst2);
//StringToCharArray(dstStr,dst2);
res=CryptDecode(CRYPT_AES256,dst2,key,src2);
// end modifications

      //--- check error     
      if(res>0)
        {
         //--- print decoded data
         PrintFormat("Decoded data: size=%d, string='%s'",ArraySize(src2),CharArrayToString(src2));
        }
      else
         Print("Error in CryptDecode. Error code=",GetLastError());
     }
   else
      Print("Error in CryptEncode. Error code=",GetLastError());

results in:

Decoded data: size=48, string='The quick brown fox jumps over tñ×vc&T̳­oQb°/'
Encoded data: size=48 A7417057F2FD37D3E7DC5CC7A4998C438995CE5A502D7C5E0AD7E65D18B57003C112834D8FB717B3EC8B7EE4B7B1F577
Initial data: size=44, string='The quick brown fox jumps over the lazy dog'

 

This whole thing is totally confusing for me.

 
franzk:

ok ... me again. Was a little quick with reporting success ;)



You should print out values of dst2[47] и dst[47] in order to understand nature of difference and then fix your errors in this awful code. But generally speaking this code must be rewritten from scratch. It is so bad....
 

Thank you for your response. The code actually comes from the example provided in the documentation for CrpytEncode() here: https://docs.mql4.com/common/cryptencode

It should just point out where my problem is.

Seems I have to add this workaround in order to make it work

uchar dst3[];
ArrayCopy(dst3,dst2,0,0,(ArraySize(dst2)-1));

 

using dst3 for decrypting afterwards because after converting the string to an array it is adding a "0" character to the array messing with the arraysize CryptDecode is expecting. Looks like a bug in StringToCharArray() maybe? In my real code I am now calling the function below instead of StringToCharArray() 

int StringToCharArrayWrap(string _str, uchar& _arr[])
{
uchar _tmpChar[];
int z=0;

StringToCharArray(_str,_tmpChar);
   if(ArraySize(_tmpChar)>StringLen(_str))
      z=1;
ArrayCopy(_arr,_tmpChar,0,0,(ArraySize(_tmpChar)-z));
return(ArraySize(_arr));   
}

All solved now (hopefully) ;)

Thanks again everyone! 

Reason: