Er zijn verschillende methodes voorgesteld om je code te beschermen, maar deze waren vaak te eenvoudig (en dus minder veilig), vereisten hercompilatie van je code voor elke nieuwe klant (prima als je maar een paar klanten hebt) of waren veel te ingewikkeld met een externe host om de client terminal te valideren.
Hier stel ik een eenvoudige wachtwoordverificatie voor die gebruikmaakt van de ingebouwde beveiligingsengine van MT4, die DES/ECB-encryptie biedt en geen hercompilatie van je code vereist voor elke nieuwe klant.
Na gewerkt te hebben aan verschillende hoogprofiel projecten in Canada met smartcards, heb ik veel geleerd over de beveiligingsschema's die door financiële instellingen en kaartuitgevers worden gebruikt. De eerste vraag die je jezelf moet stellen is: "Wat is het risico?" Een risicoanalyse wordt altijd uitgevoerd bij het beginnen van een project met deze partijen. Als het antwoord "Miljoenen en miljoenen euro's" is, dan is dit beveiligingsschema niet voor jou.
Als je daarentegen antwoordt met "Een maand of twee coderen als iemand een jaar aan mijn beveiligingsschema knaagt", dan is deze oplossing iets voor jou. De enkele DES-sleutel die in dit encryptieschema wordt gebruikt, biedt meer dan voldoende beveiliging voor je code en vereist geen hercompilatie van de code voor nieuwe klanten.
Ik heb twee bronbestanden voor je toegevoegd. Het eerste bestand, "Password_Check", is wat je toevoegt aan je indicator of Expert Advisor. Het verifieert het door de gebruiker ingevoerde wachtwoord in de invoerparameter "Password". Als het wachtwoord onjuist is (of als de gebruiker offline is), wordt er een gebruiksvriendelijke melding weergegeven, wordt de expert (als die draait) verwijderd en wordt er een INIT_FAILED-status geretourneerd.
Het tweede bestand, "Password_Generate", gebruik je om de naam en het accountnummer van de klant in te voeren die je wilt beschermen. Het genereert en toont het wachtwoord, zodat je dit aan je klanten kunt geven. Uiteraard wil je deze code niet in je eindproduct opnemen! :)
Laten we beginnen...
Eerst moeten we een invoerstring definiëren voor je indicator of Expert Advisor:
//--- invoerparameters extern string Password;
Vervolgens voegen we code toe in de init() functie om het wachtwoord te controleren en een bericht weer te geven als het wachtwoord onjuist is, als de gebruiker offline is of als de gebruiker simpelweg geen wachtwoord heeft ingevoerd.
//+------------------------------------------------------------------+ //| Expert initialisatie functie | //+------------------------------------------------------------------+ int init() { string client = NULL; // Zorg ervoor dat de klant online is om zijn naam en accountnummer te krijgen if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME) + " / " + DoubleToStr(AccountInfoInteger(ACCOUNT_LOGIN), 0); // Controleer het wachtwoord van de klant if(!Password_Check(client)) { if(StringLen(Password) != 0) MessageBox("Kan klant- en accountnummer niet verifiëren!" + (IsConnected() ? "\nControleer of je het juiste wachtwoord hebt." : "\n\nJe moet online zijn voor verificatie."), (IsConnected() ? "Ongeldig Wachtwoord!" : "Offline!"), MB_OK | MB_ICONSTOP); else MessageBox("Ongeautoriseerde software.\n\nNeem contact op met de softwareleverancier om\njouw persoonlijke activatiewachtwoord te verkrijgen." + (StringLen(client) == 0 ? "" : "\n\nJouw registratie-informatie is:\n\n'"+client+"'"), "Ongeautoriseerd", MB_OK | MB_ICONSTOP); // Ongeldig wachtwoord of gebruiker is offline. Verwijder expert en sluit met fout ExpertRemove() ; return(INIT_FAILED); } // Alles goed... return(INIT_SUCCEEDED); }
Nu komt het belangrijkste... We moeten de naam van de klant en het accountnummer coderen met onze DES-sleutel, het resultaat omzetten naar BASE64 en vergelijken met het ingevoerde wachtwoord. Als het resultaat overeenkomt, heb je een blije klant. Als dat niet zo is, heb je te maken met een hacker die probeert je DES-sleutel te kraken. Gezien het feit dat de expert advisor zichzelf telkens zal verwijderen bij een verkeerd ingevoerd wachtwoord, heb je waarschijnlijk tijd genoeg om met pensioen te gaan in Bora Bora voordat ze succes hebben!
//+------------------------------------------------------------------+ //| Valideer het wachtwoord van de klant //+------------------------------------------------------------------+ bool Password_Check(string client) { string MasterKey; uchar dst[], src[], key[]; // Definieer je encryptiesleutel hier. Moet 7 karakters zijn voor DES/ECB-encryptie // Maak je wachtwoord moeilijk te raden. Je achternaam is geen goed idee! // Iets als "wLdU&$z" zou goed zijn. Voor nu gebruiken we een simpele... MasterKey = "NotDemo"; // Zet MasterKey om naar karakterarray StringToCharArray(MasterKey, key); // Zorg ervoor dat de klantstring niet null is if(StringLen(client) == 0) return(false); // Versleutel de klant met de DES-sleutel StringToCharArray(client, src); CryptEncode(CRYPT_DES, src, key, dst); // Wis de sleutel en zet om naar BASE64 ArrayInitialize(key, 0x00); CryptEncode(CRYPT_BASE64, dst, key, src); // Vergelijk wachtwoord en retourneer resultaat return(CharArrayToString(src) == Password); }
Dat is het! We kunnen nu de klantnaam (zoals opgehaald uit de klantaccountnaam van MetaTrader 4) en het klantaccountnummer (ook afkomstig van MetaTrader 4) valideren.
Als je licentiebeleid toestaat dat meerdere accounts voor één klant kunnen worden gebruikt, hoef je alleen het accountnummer uit de 'client'-string te verwijderen, als volgt:
// Zorg ervoor dat de klant online is om de klantnaam te krijgen if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME);
Natuurlijk kun je een mix en match doen met "Broker Naam", "Account Naam" en "Account Login" zoals jij dat wilt. Vergeet niet dat hoe langer de 'client'-variabele is, hoe langer het versleutelde wachtwoord zal zijn.
Laten we nu eens kijken naar de code van "Password_Generate". Wat we willen doen is hetzelfde als bij "Password_Check", maar in plaats van een wachtwoord in de EA in te voeren, willen we de klantnaam (of combinatie van Broker Naam, Account Naam en Account Login die je kiest) invoeren om te versleutelen en vervolgens het gegenereerde wachtwoord weer te geven. Dit is wat je aan je klanten geeft wanneer ze je geweldige indicator en/of Expert Advisor kopen.
Opnieuw voeg je de volgende code toe in je init() functie.
//+------------------------------------------------------------------+ //| Expert initialisatie functie | //+------------------------------------------------------------------+ int init() { string Password = NULL; // Zorg ervoor dat de Klant invoer niet leeg is if(StringLen(Client) != 0) { // Genereer een klantwachtwoord Password = Password_Generate(Client); // Print het gegenereerde wachtwoord (maakt het gemakkelijk om te kopiëren en plakken) Print("Klant: '"+Client+"' Wachtwoord: "+Password); // Toon het voor de klant gegenereerde wachtwoord MessageBox("Wachtwoord gegenereerd voor klant/account\n\n'"+Client+"' is:\n"+Password, "Wachtwoord Generator", MB_OK | MB_ICONINFORMATION); } else MessageBox("Je moet een klant/accountnummer opgeven!", "Wachtwoord Generator", MB_OK | MB_ICONSTOP); // Alles goed. Verwijder expert. ExpertRemove(); return(INIT_SUCCEEDED); }
Nu doen we een kleine wijziging aan onze "Password_Check()" functie om een string van het versleutelde wachtwoord te retourneren. Vergeet niet hetzelfde wachtwoord te gebruiken in zowel de Password_Check() functie als de Password_Generate() functie. Je kunt je voorstellen wat er gebeurt als je dat niet doet!
//+------------------------------------------------------------------+ //| Versleutel klantinformatie en retourneer het wachtwoord //+------------------------------------------------------------------+ string Password_Generate(string client) { string MasterKey; uchar dst[], src[], key[]; // Definieer je encryptiesleutel hier. Moet 7 karakters zijn voor DES/ECB-encryptie // HET MOET DEZELFDE WACHTWOORD ZIJN ALS GEEFT IN DE "Password_Check()" FUNCTIE! // Maak je wachtwoord moeilijk te raden. Je achternaam is geen goed idee! // Iets als "wLdU&$z" zou goed zijn. Voor nu gebruiken we een simpele... MasterKey = "NotDemo"; // Zet MasterKey om naar karakterarray StringToCharArray(MasterKey, key); // Versleutel de klant met de DES-sleutel StringToCharArray(client, src); CryptEncode(CRYPT_DES, src, key, dst); // Wis de sleutel en zet om naar BASE64 ArrayInitialize(key, 0x00); CryptEncode(CRYPT_BASE64, dst, key, src); // Retourneer het versleutelde wachtwoord return(CharArrayToString(src)); }
Dat is het, dat is alles. Je voert de informatie in die je van je klant hebt gekregen en je stuurt hen het wachtwoord per e-mail of op een andere manier die je kiest. Natuurlijk is het mooie van dit alles dat je dit vanuit je woonkamer in Bora Bora kunt doen!
Zoals eerder vermeld, vereist dit beveiligingsschema geen hercompilatie van je code voor elke nieuwe klant of het coderen van een server-side validatiehost, terwijl het toch een behoorlijke beveiliging biedt voor je harde werk bij het creëren van die geweldige indicator / Expert Advisor van jou!
Proost!
-Claude.
Gerelateerde berichten
- MQL5 Wizard: Handelsignalen Geïnspireerd Door Morning/Evening Stars + MFI voor MetaTrader 5
- MQL5 Wizard: Handelsignalen Geïnspireerd door Morning/Evening Stars en RSI voor MetaTrader 5
- Schnick: Ondersteunende Vector Machine Leerhulpmiddel voor MetaTrader 5
- Geschiedenis Downloader - handige tool voor MetaTrader 4
- Handelssignalen met MQL5 Wizard: EMA Crossover Strategie met Tijdfilter