Download MetaTrader 5

Watch how to download trading robots for free

Interesting script?
So post a link to it -
let others appraise it

You liked the script? Try it in the MetaTrader 5 terminal

2016.05.25 13:11
Adding password protection to your Indicator / Expert Advisor

Adding password protection to your Indicator / Expert Advisor - expert for MetaTrader 4

| English Español Português 日本語 Deutsch

Views:
5182
Rating:
votes: 10

Several methods of protecting your code have been proposed over the past, but were either too simple (less secure), required re-compilation of your code for each new customer (ok if you only plan on having a dozen or so customers) or far too complicated involving a remote host to validate the client terminal.

Here I propose a simple password verification scheme which uses MT4's built in security engine providing DES/ECB encryption and does not require code re-compilation for each new customer.

Having worked on several high profile Canadian smart card initiatives, I became quite familiar with the various security schemes used by financial institutions and card issuers. The first question you have to ask yourself is "What's at risk?". A risk assessment is always done when starting a project with these guys. If the answer is "Millions and millions of dollars", then this security scheme is not for you.

If, on the other hand, your answer is "A month or two of coding if somebody spends about a year hacking my security scheme", then this solution is for you. The single DES key used in this encryption scheme will provide more than adequate security for your code and will not require code re-compilation for new clients.

I have provided two source files for your convenience. The first one "Password_Check" is what you will add to your indicator or expert advisor. It will verify the password entered by the user in the input parameter "Password" and if the password is incorrect (or if the user is offline) it will display a user friendly message, remove the expert (if that's what's running) and return a INIT_FAILED status.

The second file, "Password_Generate", is used to enter the client's name and account number you want to protect. It will display the password generated so you can provide this to your clients. Obviously, you don't want to include this code in your final product! :)

So let's get started...

First, we need to define an input string to your indicator or Expert Advisor:

//--- input parameters
extern string     Password;

Next, we add code in the init() function to check the password and display a message if the password is incorrect, if the user is offline or the user simply didn't enter a password.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
   string   client = NULL;
   
   // Make sure the client is online in order to get his client name and account number
   if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME) + " / " + DoubleToStr(AccountInfoInteger(ACCOUNT_LOGIN), 0);

   // Check client's password
   if(!Password_Check(client))
   {
      if(StringLen(Password) != 0)
         MessageBox("Unable to verify client and account number!" + 
            (IsConnected() ? "\nPlease verify you have the correct password." : "\n\nYou need to be online for verification."), 
            (IsConnected() ? "Invalid Password!" : "Offline!"), MB_OK | MB_ICONSTOP);
      else
         MessageBox("Unregistered software.\n\nPlease contact software vendor to obtain\nyour personal activation password." +
            (StringLen(client) == 0 ? "" : "\n\nYour registration information is:\n\n'"+client+"'"), 
            "Unregistered", MB_OK | MB_ICONSTOP);
      
      // Invalid password or user is offline.  Remove expert and exit with error
      ExpertRemove();
      return(INIT_FAILED);
   }

   // All good...
   return(INIT_SUCCEEDED);
}

Now come the meat... We need to encode the client name and account number with our DES key, encode the result into BASE64 and compare with the password entered. If the result matches, you have a happy customer. If they don't, you have a hacker trying to crack your DES key. Given that the expert advisor will unload itself each time a wrong password is entered, you'll probably have time to retire in Bora Bora before they succeed!

//+------------------------------------------------------------------+
//| Validate client's password
//+------------------------------------------------------------------+
bool Password_Check(string client)
{
   string   MasterKey;
   uchar dst[], src[], key[];

   // Define your encryption key here.  Must be 7 characters for DES/ECB encryption
   // Make your password difficult to figure out.  You last name is not a good idea!
   // Something like "wLdU&$z" would be good.  For now, we'll use a simple one...
   MasterKey = "NotDemo";  
   
   // Convert MasterKey to character array
   StringToCharArray(MasterKey, key);
   
   // Make sure client string is not null
   if(StringLen(client) == 0) return(false);
   
   // Encrypt the client using DES key
   StringToCharArray(client, src);
   CryptEncode(CRYPT_DES, src, key, dst);

   // Clear key and encode to BASE64
   ArrayInitialize(key, 0x00);
   CryptEncode(CRYPT_BASE64, dst, key, src);

   // Compare password and return result
   return(CharArrayToString(src) == Password);
}

That's it! We can now validate the client name (as taken from MetaTrader 4's client account name) plus the client account number (also taken from MetaTrader 4).

If your licensing policy is to allow multiple accounts for a single client, then you only need to remove the account number from the 'client' string, as follows:

// Make sure the client is online in order to get the client name
if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME);

Of course you can do a mix and match with "Broker Name", "Account Name" and "Account Login" the way you see fit. Just remember that the longer the 'client' variable is, the longer the encrypted password will be.

Next, let's take a look at the "Password_Generate" code. What we want to do is the same as the "Password_Check" but instead of entering a password into the EA, we want to enter the client name (or combination of Broker Name, Account Name and Account Login you choose) to be encrypted and then display the generated password. This is what you'll give to your clients when they purchase your kick-ass indicator and/or Expert Advisor.

Again, in your init() function you'll add the following code.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
   string   Password = NULL;

   // Make sure the Client input is not empty
   if(StringLen(Client) != 0)
   {   
      // Generate a client password
      Password = Password_Generate(Client);
   
      // Print the generated password (makes it easy to cut and paste)
      Print("Client: '"+Client+"'  Password: "+Password);
      
      // Display the password generated for client
      MessageBox("Password generated for client / account\n\n'"+Client+"' is:\n"+Password, "Password Generator", 
         MB_OK | MB_ICONINFORMATION);
   }
   else
      MessageBox("You must specify a client / account number!", "Password Generator", MB_OK | MB_ICONSTOP);
         
   // All good.  Remove expert.
   ExpertRemove();
   return(INIT_SUCCEEDED);
}

Now we do a slight modification to our "Password_Check()" function to return a string of the encoded password. Remember to use the same password in BOTH the Password_Check() function and Password_Generate() function. You can image what will happen if you don't!

//+------------------------------------------------------------------+
//| Encrypt client information and return the password
//+------------------------------------------------------------------+
string Password_Generate(string client)
{
   string   MasterKey;
   uchar dst[], src[], key[];

   // Define your encryption key here.  Must be 7 characters for DES/ECB encryption
   // IT MUST BE THE SAME PASSWORD AS DEFINE IN THE "Password_Check()" function!
   // Make your password difficult to figure out.  You last name is not a good idea!
   // Something like "wLdU&$z" would be good.  For now, we'll use a simple one...
   MasterKey = "NotDemo";  
   
   // Convert MasterKey to character array
   StringToCharArray(MasterKey, key);
   
   // Encrypt the client using DES key
   StringToCharArray(client, src);
   CryptEncode(CRYPT_DES, src, key, dst);

   // Clear key and encode to BASE64
   ArrayInitialize(key, 0x00);
   CryptEncode(CRYPT_BASE64, dst, key, src);

   // Return encypted password
   return(CharArrayToString(src));   
}

That's it, that's all. You enter the information provided to you by your client and you send them the password by email or whatever other means you choose. Of course, the beauty of this is that you can do this from your living room in Bora Bora!

As stated before, this security scheme does not require you re-compile your code for each new customer or code a server side validation host while providing pretty good security for your hard work creating that kick-ass indicator / Expert Advisor of yours!

Cheers!

-Claude.

Accelerator Oscillator (AC) Accelerator Oscillator (AC)

The Acceleration/Deceleration Indicator (AC) measures acceleration and deceleration of the current driving force.

Average Directional Movement Index (ADX) Average Directional Movement Index (ADX)

The Average Directional Movement Index Indicator (ADX) helps to determine if there is a price trend.

LinesProfitLoss LinesProfitLoss

Calculates profit (loss) of the current orders on the symbol.

FFC - Forex Factory Calendar FFC - Forex Factory Calendar

Modified version of FF Calendar Indicator with new features.