Libraries: Hash functions library

 

Hash functions library:

The library contains the following hash functions: adler32, CRC-32, MaHash8v64. Also it has functions for radix conversion of a number.

General purpose hash functions:

  • adler32
  • CRC-32 (fast, table implementation)
  • MaHash8v64 (fast, table implementation)

All three functions are adapted for MQL5 Unicode strings. The results has been verified with Fsum Frontend 1.5.5.1.

Radix Conversion:

  • from decimal (ulong) to Base radix
  • inverse transformation

The radix conversion is based on the following sequence of chars: 10 [0..9] + 26 [A..Z] + 26 [a..z] + 33 [А..Я] + 33 [а..я].  The "0-9" digits and "A-Z" english letters are used up to base 36.

Author: Александр

 

Good afternoon!

The task is to track the moments of change of a set of collections of complex objects. I can convert an object and a collection into a string, it will be about 2000 characters per collection. Can you tell me which library function will be more correct to get a short representation of such a long string?

Документация по MQL5: Основы языка / Типы данных / Тип string
Документация по MQL5: Основы языка / Типы данных / Тип string
  • www.mql5.com
Тип string предназначен для хранения текстовых строк. Текстовая строка представляет собой последовательность символов в формате Unicode с завершающим нулем на конце. string-переменной может быть назначена строковая константа. Строковая константа представляет собой последовательность символов Unicode, заключенную в двойные кавычки: "Это...
 
Nikolai Karetnikov:

Good afternoon!

The task is to track the moments of change of a set of collections of complex objects. I can convert an object and a collection into a string, it will be about 2000 characters per collection. Can you tell me which library function will be more correct to get a short representation of such a long string?

CryptEncode/Decode and choose HASH_xxx methods.

you can even ZIP :-) a regular text of 2000 printable characters is a paltry 200-300 bytes, it can fit into 4 long`es.

 

ErrorCryptDecode(CRYPT_BASE64

int OnInit()
{
   string text="";
   string res="";
   string key="fuyTkH3cd63K9Htrl2xdFgjerPjmla8h";

   text="indicator_chart_window";
   if(!CryptEncodeA(text,key,res))
      Print("Error: Encode:",GetLastError());

   Print(res);

   text="vj9jDk+GxxB4W1zQc4/rC4OPvttMcgcF5ZFVC7m7l50=";
   if(!CryptDecodeA(text,key,res))
      Print("Error: Decode:",GetLastError());

   Print(res);
   return(INIT_SUCCEEDED);
}

//------------------------------------------------------------------
bool CryptEncodeA(string InputText,string key,string &Output) {
   uchar scr[];
   uchar dst[];
   uchar res[];
   uchar key_aes256[];
   uchar key_base64[];
   StringToCharArray(InputText,scr);
   StringToCharArray(key,key_aes256);
   if(CryptEncode(CRYPT_AES256,scr,key_aes256,dst)==0) return(false);
   if(CryptEncode(CRYPT_BASE64,dst,key_base64,res)==0) return(false);
   Output = CharArrayToString(res);
   return(true);
}
//--
bool CryptDecodeA(string InputText,string key,string &Output) {
   uchar scr[];
   uchar dst[];
   uchar res[];
   uchar key_base64[];
   uchar key_aes256[];
   StringToCharArray(InputText,scr);
   StringToCharArray(key,key_aes256);
   if(CryptDecode(CRYPT_BASE64,scr,key_base64,dst)==0) return(false);
   if(CryptDecode(CRYPT_AES256,dst,key_aes256,res)==0) return(false);
   Output = CharArrayToString(res);
   return(true);
}

---

The CryptEncodeA function creates a string, which thenCryptDecodeA cannot decrypt and gives an error in mt4: "4029", in mt5: "4006". The terminal has encrypted that it cannot decrypt itself.

Line from the log: vj9jDk+GxxB4W1zQc4/rC4OPvttMcgcF5ZFVC7m7l50=

If you remove the last "="- then it will decrypt and there is no error.

At the same time, php decodes normally and correctly:

$secret_key = 'fuyTkH3cd63K9Htrl2xdFgjerPjmla8h';

$s = "indicator_chart_window";
$res = base64_encode(openssl_encrypt($s,"AES-256-ECB",$secret_key,OPENSSL_RAW_DATA));
echo $res.'<br>';

$s= "vj9jDk+GxxB4W1zQc4/rC54fEtkLAsAONkyeprqmMlw=";
$res = openssl_decrypt(base64_decode($s),"AES-256-ECB",$secret_key,OPENSSL_ZERO_PADDING|OPENSSL_RAW_DATA);
echo $res;

---

Encrypt the same string on the server: "indicator_chart_window".

Get the result:"vj9jDk+GxxB4W1zQc4/rC54fEtkLAsAONkyeprqmMlw=""

We insert this line into mql code and again we get an error - remove the last "=" and everything works fine.

---

I put some random encryption key, on the server the string is: "8CpXr3OlVhGs41syHA0+HqZKnatswQjRWn2fKYN4qN4=="

I inserted the string into mql-code - error,removed one "=" leaving only one - worked fine (what was the key that created a string with two equals - I could not reproduce)

I want to get an answer, maybe I'm doing something wrong!

P.S. I have attached all the codes, what could be the problem?
 

The StringToArray function captures the termination zero if you do not specify the length of the string (historically)

Therefore, in the CryptDecodeA function you should use

StringToCharArray(InputText,scr,0,StringLen(InputText));

instead of

StringToCharArray(InputText,scr);
Документация по MQL5: Общие функции / CryptDecode
Документация по MQL5: Общие функции / CryptDecode
  • www.mql5.com
CryptDecode - Общие функции - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Ilyas:

The StringToArray function captures the termination zero if you do not specify the length of the string (historically)

Therefore, in the CryptDecodeA function you should use

instead of

@Ilyas

I checked it in different variations - everything works.

One problemremains:

StringReplace(res,"\x00..\x1F",""); // Не помогает

How to remove non-printing characters?

Thanks!

 
Vitaly Muzichenko:

@Ilyas

Checked in different variations - everything works.

One problemremains:

How to remove non-printing characters?

Thank you!

There is no function in MQL with the functionality you need

It is easier to do it before converting the array to a string:

//+------------------------------------------------------------------+
//|ArrayToString.mq5 |
//| Copyright 2021, MetaQuotes Software Corp. | |
//|https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
template<typename TChar>
string ArrayToString(const TChar &input_array[],bool remove_non_printable=false,int start=0,int count=-1,int codepage=CP_ACP)
  {
   struct cvt
     {
      static string convert(const uchar &input_array[],int start=0,int count=-1,int codepage=CP_ACP) { return(CharArrayToString(input_array,start,count,codepage)); }
      static string convert(const short &input_array[],int start=0,int count=-1,int codepage=CP_ACP) { return(ShortArrayToString(input_array,start,count)); }      
     };
  
   int input_size =ArraySize(input_array);
//--- no data to convert
   if(start>=input_size || count==0)
      return(NULL);
//--- fix start parameter
   if(start<0)
      start=0;
//--- fix count parameter
   if(count<0 || count==WHOLE_ARRAY || (start+count)>input_size)
      count=input_size-start;
//--- convert input array as it is
   if(!remove_non_printable)
      return(cvt::convert(input_array,start,count,codepage));
//--- remove non printable symbols from input array
   TChar cvt_array[];
   int   cvt_size=0;

   if(!ArrayResize(cvt_array,input_size))
      return(NULL);

   for(int i=0,n=start; i<input_size; i++)
     {
      const TChar input_sym = input_array[n++];
      //--- check for negative, input_array can be signed
      if(input_sym>0 && input_sym<' ')
         continue;
      //--- zero is terminator
      if(input_sym==0)
         break;
      //--- copy input symbol
      cvt_array[cvt_size++]=input_sym;
     }
//--- convert cleaned array to string
   return(cvt::convert(cvt_array,0,cvt_size));
  }
//+------------------------------------------------------------------+
//| Script programme start function|
//+------------------------------------------------------------------+
void OnStart()
  {
   uchar input_array_uc[]= { 1, 'T', 2, 'h', 3, 'e', 4, ' ', 5, 'q', 6, 'u', 7, 'i', 8, 'c', 9, 'k', 10, ' ', 11, 'b', 12, 'r', 13, 'o', 14, 'w', 15, 'n', 16, ' ', 15, 'f', 16, 'o', 17, 'x', 18, ' ', 19, 'j', 20, 'u',
                            21, 'm', 22, 'p', 23, 's', 24, ' ', 25, 'o', 26, 'v', 27, 'e', 28, 'r', 29, ' ', 30, 't', 31, 'h','e',' ','l','a','z','y',' ','d','o','g','.', 0, 'X', 'X', 'X', 'X', 'X', 'X' };
   short input_array_s []= { 1, 'T', 2, 'h', 3, 'e', 4, ' ', 5, 'q', 6, 'u', 7, 'i', 8, 'c', 9, 'k', 10, ' ', 11, 'b', 12, 'r', 13, 'o', 14, 'w', 15, 'n', 16, ' ', 15, 'f', 16, 'o', 17, 'x', 18, ' ', 19, 'j', 20, 'u',
                            21, 'm', 22, 'p', 23, 's', 24, ' ', 25, 'o', 26, 'v', 27, 'e', 28, 'r', 29, ' ', 30, 't', 31, 'h','e',' ','l','a','z','y',' ','d','o','g','.', 0, 'X', 'X', 'X', 'X', 'X', 'X' };

   Print("without removing non-printables");
   Print(ArrayToString(input_array_uc));
   Print(ArrayToString(input_array_s));

   Print("with removing non-printables");
   Print(ArrayToString(input_array_uc,true));
   Print(ArrayToString(input_array_s,true));
  }
//+------------------------------------------------------------------+