Error CryptDecode - page 2

 
franzk:

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

 

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() 

All solved now (hopefully) ;)

Thanks again everyone! 

Actually, that works fine:

 

 void OnStart()

//+------------------------------------------------------------------+

{

   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 AES 256-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[]


      //--- decrypt dst[] with AES 256-bit key in key[]

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


      //--- 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());

}


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);

  }

 
You need to set the size of the char array with StringLen() in the function call:

string String = "Some string";
uchar  CharString[];
StringToCharArray(String,CharString,0,StringLen(String));

The array will then be the proper size. You'd think this would happen automatically... When dealing with function issues, always look up the parameters: https://docs.mql4.com/convert/stringtochararray
 

My snippet for this post, but remember this rule first :

 

 

 

I made a class with 2 functions "Encrypt" and "DeCrypt" :

 

class Crypter{
   
   public :
   
      Crypter( void );
               
      ~Crypter( void );

      string EnCrypt
      (
         ENUM_CRYPT_METHOD method,
         string toKey,
         string toEnCrypt
      
      );
      
      string DeCrypt
      (
         ENUM_CRYPT_METHOD method,
         string toKey,
         string toDeCrypt
      
      );

};

Crypter::Crypter( void ){ /* TODO */ };
Crypter::~Crypter( void ){ /* TODO */ };

string AwesomeUtilityGlobalClass_1_0_0::EnCrypt
(
   ENUM_CRYPT_METHOD method,
   string toKey,
   string toEnCrypt

){

   uchar src[],dst[],key[];
   
   StringToCharArray( toKey, key, 0, StringLen( toKey ) );
   StringToCharArray( toEnCrypt,src, 0, StringLen( toEnCrypt ) );

   int res = CryptEncode( method, src, key, dst );
   
   return ( res > 0 ) ? CharArrayToString( dst ) : "";

};

string AwesomeUtilityGlobalClass_1_0_0::DeCrypt
(
   ENUM_CRYPT_METHOD method,
   string toKey,
   string toDeCrypt

){

   uchar src[],dst[],key[];
   
   StringToCharArray( toKey, key, 0, StringLen( toKey ) );
   StringToCharArray( toDeCrypt, src, 0, StringLen( toDeCrypt ) );   

   int res = CryptDecode( method, src, key, dst );

   return ( res > 0 ) ? CharArrayToString( dst ) : "";

};

 

 

Save this class with "Crypt.mqh", then import in to your project for example :

#include "Crypt.mqh"

// Global object
Crypter AU;

// Now test your pass keys and method
int OnInit(){
   
   string MexToCrypt = "Awesome message for you, Hello World ! XD";
   string Password = "This Is My Password ! Ehmmmm you like my password ?";
   Print( MexToCrypt, " ", Password );
   
   ENUM_CRYPT_METHOD CryptoMethod   = CRYPT_AES128;
   ENUM_CRYPT_METHOD CryptoMethodTO = CRYPT_BASE64;
   
   string Crypted = AU.EnCrypt( CryptoMethod, Password, MexToCrypt );
   string CryptedTo64 = AU.EnCrypt( CryptoMethodTO, Password, Crypted );
   PrintFormat( "B64 : %s", CryptedTo64 );
   
   string DecryptedFrom64 = AU.DeCrypt( CryptoMethodTO, Password, CryptedTo64 );
   string DeCrypted = AU.DeCrypt( CryptoMethod, Password, DecryptedFrom64 );   
   PrintFormat( "Decripted : %s", DeCrypted );
            
   return( INIT_SUCCEEDED );

}

 

 Result :

 

 

 

I hope this help, enjoy ;) 

 
Matthew Schmieder:
You need to set the size of the char array with StringLen() in the function call:


The array will then be the proper size. You'd think this would happen automatically... When dealing with function issues, always look up the parameters: https://docs.mql4.com/convert/stringtochararray
if you have problem with decode process, set size of the char array for me is the best solution, thank you for pointing it out :)
 
Hi Guys,


I'm having a problem decrypting a string using the CRYPT_AES256 method.

The string is generated by another application (VB) using this method, the string is in the HEX format output as per the ArrayToHex(dst) function that is in the documentation.


//+------------------------------------------------------------------+
//| 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);
  }



e.g. "B9343FE511F1FE0C62167F2D9F6332A81BBA93185C9DCDA9990E9C6C98D12CE3F1988C73CC38DE5B9B00EE9A06203264"


How do I convert the HEX string back to an array that can be passed into the CryptDecode function as per the example in the documentation?

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


I thought this would be simple but keep getting the error 4029.

I've spent 5 hours on this and am fried! I have the 256 bit key and can take the output from ArrayToHex(dst) and use it in my other application (VB) convert back no problem.

My VB app outputs the HEX string in the format as per ArrayToHex(dst) to a file for use with MT4.

From my MT4 program I read in the file and try to decode it but all I get is error 4029. I've tried some of the ideas on this thread regarding the additional character being added by the character array conversion process but so far no joy.

I need to effectively reverse the string output of ArrayToHex(dst). I've tried creating a function called HexToArray() but also no joy.

MQL4 is not my main language so feel pretty frustrated, any help would be very appreciated :)

thx,

Phill.
 
 
asurething:
...
You don't show your code, how do you think someone could help ?
 
Hi,

After a few hours break I can hopefully explain better my problem.


I have a VB app that supports AES256, I need to pass an encrypted string from the VB app to my MQL4 code.

The following MQL4 code below works ok. I can take the contents of the array dst after encryption and use the function ArrayToHex(dst) to output the string:

"6301C0EA82F634C8233F5BDA0DBEBBE514273696BD31E07F1FCE446CAC4E848220693EC82BB045C41E940A8048853140"

I can take this string and decrypt it perfectly with my VB app to get the string:

"The quick brown fox jumps over the lazy dog"

So far so good.

However, if I try and go the other direction I have a problem. When I generate and save the above string to a file from my VB app and read in the file via my MQL4 code using the lines:

nextline=FileReadString(file_handle);
            PrintFormat(nextline);

nextline  =  "6301C0EA82F634C8233F5BDA0DBEBBE514273696BD31E07F1FCE446CAC4E848220693EC82BB045C41E940A8048853140"

(What was the output of ArrayToHex below), next I want to decrypt it to get:

"The quick brown fox jumps over the lazy dog"

I have the key ("59IJDBS009JSENRVJVDPLWRJRIVF49II") and know its using CRYPT_AES256 yet no matter what I try I get the error 4029.


I can't seem to set the array src up correctly using the value of nextline.

How do I switch it back into the format of the array src that acted as the input for ArrayToHex(dst) so I can decrypt it using the line:

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

I'm missing something real simple here but I can't see it for looking at it.

Any thoughts..........

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()

//+------------------------------------------------------------------+

{

   string text="The quick brown fox jumps over the lazy dog";
   string keystr="59IJDBS009JSENRVJVDPLWRJRIVF49II";
   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[]
      res=CryptDecode(CRYPT_AES256,dst,key,src);
      //--- 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());
  }
 
Apologies, here is my function to open the file and decrypt the string read in from it.

When I decrpyt res always = 0

thx...

//+------------------------------------------------------------------+
//| function to decrypt string from VB app                           |
//+------------------------------------------------------------------+ 
bool DeCrpytString()
{

int res=0;

long search_handle=0;
long file_handle=0;

string file_folder="bss\\tradedata";

string file_name="decrypt-me.dat";

string nextline="";

ResetLastError();
   
file_handle=FileOpen(file_folder+"\\"+file_name,FILE_COMMON|FILE_READ|FILE_TXT);
  
if(file_handle!=INVALID_HANDLE)
   {
                                           
      while(!FileIsEnding(file_handle))
     
        {
            nextline=FileReadString(file_handle);
            PrintFormat(nextline);
       
            // nextline="6301C0EA82F634C8233F5BDA0DBEBBE514273696BD31E07F1FCE446CAC4E848220693EC82BB045C41E940A8048853140"
           
            FileClose(file_handle);                                     // close file as its only a one liner
         
            if(nextline=="")                                            // if empty file
               {
                   PrintFormat("empty file %s file, Error code = %d",file_name,GetLastError());
                   return(false);
               }
       
            // now decrypt nextline to get "The quick brown fox jumps over the lazy dog"
        
            string keystr="59IJDBS009JSENRVJVDPLWRJRIVF49II";        // same key as used by VB app
        
            uchar src[],dst[],key[];

            StringToCharArray(keystr,key);                           //--- prepare key
 
            StringToCharArray(nextline,src);                         //--- prepare encrypted string

            PrintFormat("Initial data: size=%d, string='%s'",ArraySize(src),CharArrayToString(src));  //--- print initial data

            PrintFormat("Encoded data: size=%d %s",res,ArrayToHex(src));      //--- print encrypted data
       
            res=CryptDecode(CRYPT_AES256,src,key,dst);      //--- decode src[] to dst[]   decrypt src[] with AES 256-bit key in key[]

            PrintFormat("Encoded data: size=%d %s",res,ArrayToHex(dst));      //--- print decrypted data

            //--- print decoded data
  
            PrintFormat("Decoded data: size=%d, string='%s'",ArraySize(dst),CharArrayToString(dst));

                    
            if(res>0)
        
              {
        
                  PrintFormat("Encoded data: size=%d %s",res,ArrayToHex(dst));      //--- print decrypted data

                  //--- print decoded data
        
                  PrintFormat("Decoded data: size=%d, string='%s'",ArraySize(dst),CharArrayToString(dst));
        
              }
            
             else
                  { 
                     Print("Error in CryptDecode. Error code=",GetLastError());
                     return(false);
                 
                  }
   
       
        }
        
   }
  
else
   {
      PrintFormat("Failed to open %s file, Error code = %d",file_name,GetLastError());
      return(false);
   }
              
FileClose(file_handle);

PrintFormat("Encrypted file: , %s file is closed",file_folder+"\\"+file_name);
 
return(true);


}
 
asurething:
...

I have the key ("59IJDBS009JSENRVJVDPLWRJRIVF49II") and know its using CRYPT_AES256 yet no matter what I try I get the error 4029.


I can't seem to set the array src up correctly using the value of nextline.

How do I switch it back into the format of the array src that acted as the input for ArrayToHex(dst) so I can decrypt it using the line:


Did you read the documentation about error 4029 ? Have you understood it ?

In one direction you are using ArrayToHex(), in the other direction you take to Hex string to put it directly in an array of char. Nothing seems missing to you ?

See this topic.
Reason: