Negli ultimi anni, sono stati proposti vari metodi per proteggere il tuo codice, ma molti di essi erano troppo semplici (meno sicuri), richiedevano la ricompilazione del codice per ogni nuovo cliente (cosa accettabile se hai solo una dozzina di clienti) o risultavano troppo complicati, coinvolgendo un host remoto per validare il terminale del cliente.
Oggi ti propongo uno schema semplice di verifica della password che utilizza il motore di sicurezza integrato di MT4, fornendo crittografia DES/ECB e non richiedendo la ricompilazione del codice per ogni nuovo cliente.
Avendo lavorato su numerosi progetti di smart card in Canada, ho acquisito una buona familiarità con i vari schemi di sicurezza utilizzati dalle istituzioni finanziarie e dagli emittenti di carte. La prima domanda da porsi è: "Qual è il rischio?". Una valutazione del rischio viene sempre effettuata all'inizio di un progetto con questi interlocutori. Se la risposta è "Milioni e milioni di euro", allora questo schema di sicurezza non fa per te.
Se invece la tua risposta è "Un mese o due di codice se qualcuno spende circa un anno a hackerare il mio schema di sicurezza", allora questa soluzione fa per te. La chiave DES singola utilizzata in questo schema di crittografia fornirà una sicurezza più che adeguata per il tuo codice e non richiederà la ricompilazione del codice per i nuovi clienti.
Per tua comodità, ho fornito due file sorgente. Il primo, "Password_Check", è quello che dovrai aggiungere al tuo indicatore o EA. Questo verificherà la password inserita dall'utente nel parametro di input "Password" e, se la password è errata (o se l'utente è offline), mostrerà un messaggio amichevole, rimuoverà l'expert (se è quello in esecuzione) e restituirà uno stato INIT_FAILED.
Il secondo file, "Password_Generate", serve a inserire il nome e il numero di conto del cliente che vuoi proteggere. Mostrerà la password generata, così potrai fornirla ai tuoi clienti. Ovviamente, non vuoi includere questo codice nel tuo prodotto finale! :)
Iniziamo...
Per prima cosa, dobbiamo definire una stringa di input per il tuo indicatore o EA:
//--- parametri di input extern string Password;
Successivamente, aggiungiamo del codice nella funzione init() per controllare la password e visualizzare un messaggio se la password è errata, se l'utente è offline o se l'utente non ha semplicemente inserito una password.
//+------------------------------------------------------------------+ //| Funzione di inizializzazione dell'Expert | //+------------------------------------------------------------------+ int init() { string client = NULL; // Assicurati che il cliente sia online per ottenere il suo nome e numero di conto if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME) + " / " + DoubleToStr(AccountInfoInteger(ACCOUNT_LOGIN), 0); // Controlla la password del cliente if(!Password_Check(client)) { if(StringLen(Password) != 0) MessageBox("Impossibile verificare il cliente e il numero di conto!" + (IsConnected() ? "\nControlla di avere la password corretta." : "\n\nDevi essere online per la verifica."), (IsConnected() ? "Password non valida!" : "Offline!"), MB_OK | MB_ICONSTOP); else MessageBox("Software non registrato.\n\nContatta il fornitore del software per ottenere\nil tuo personale codice di attivazione." + (StringLen(client) == 0 ? "" : "\n\nLe tue informazioni di registrazione sono:\n\n'"+client+"'"), "Non registrato", MB_OK | MB_ICONSTOP); // Password non valida o utente offline. Rimuovi l'expert ed esci con errore ExpertRemove(); return(INIT_FAILED); } // Tutto a posto... return(INIT_SUCCEEDED); }
Ora arriva il bello... Dobbiamo codificare il nome del cliente e il numero di conto con la nostra chiave DES, codificare il risultato in BASE64 e confrontarlo con la password inserita. Se il risultato corrisponde, hai un cliente felice. Se no, hai un hacker che cerca di rompere la tua chiave DES. Dato che l'expert advisor si disinstallerà ogni volta che viene inserita una password errata, probabilmente avrai il tempo di ritirarti a Bora Bora prima che ci riescano!
//+------------------------------------------------------------------+ //| Convalida la password del cliente //+------------------------------------------------------------------+ bool Password_Check(string client) { string MasterKey; uchar dst[], src[], key[]; // Definisci qui la tua chiave di crittografia. Deve essere di 7 caratteri per la crittografia DES/ECB // Rendila difficile da indovinare. Il tuo cognome non è una buona idea! // Qualcosa come "wLdU&$z" sarebbe buono. Per ora, useremo una semplice... MasterKey = "NotDemo"; // Converti MasterKey in array di caratteri StringToCharArray(MasterKey, key); // Assicurati che la stringa del cliente non sia nulla if(StringLen(client) == 0) return(false); // Cripta il cliente utilizzando la chiave DES StringToCharArray(client, src); CryptEncode(CRYPT_DES, src, key, dst); // Pulisci la chiave e codifica in BASE64 ArrayInitialize(key, 0x00); CryptEncode(CRYPT_BASE64, dst, key, src); // Confronta la password e restituisci il risultato return(CharArrayToString(src) == Password); }
Ed ecco fatto! Possiamo ora convalidare il nome del cliente (preso dal nome dell'account del cliente di MetaTrader 4) e il numero di conto (anch'esso preso da MetaTrader 4).
Se la tua politica di licensing consente più conti per un singolo cliente, dovrai semplicemente rimuovere il numero di conto dalla stringa 'client', come segue:
// Assicurati che il cliente sia online per ottenere il nome del cliente if(IsConnected()) client = AccountInfoString(ACCOUNT_NAME);
Naturalmente, puoi mescolare e abbinare "Nome Broker", "Nome Account" e "Login Account" come preferisci. Ricorda solo che più lunga è la variabile 'client', più lunga sarà la password crittografata.
Passiamo ora a dare un'occhiata al codice "Password_Generate". Ciò che vogliamo fare è lo stesso di "Password_Check", ma invece di inserire una password nell'EA, vogliamo inserire il nome del cliente (o la combinazione di Nome Broker, Nome Account e Login Account che scegli) da crittografare e quindi mostrare la password generata. Questa è quella che fornirai ai tuoi clienti quando acquistano il tuo fantastico indicatore e/o Expert Advisor.
Ancora una volta, nella tua funzione init() aggiungerai il seguente codice.
//+------------------------------------------------------------------+ //| Funzione di inizializzazione dell'Expert | //+------------------------------------------------------------------+ int init() { string Password = NULL; // Assicurati che l'input del Cliente non sia vuoto if(StringLen(Client) != 0) { // Genera una password per il cliente Password = Password_Generate(Client); // Stampa la password generata (facilita il taglia e incolla) Print("Cliente: '"+Client+"' Password: "+Password); // Mostra la password generata per il cliente MessageBox("Password generata per cliente / conto\n\n'"+Client+"' è:\n"+Password, "Generatore di Password", MB_OK | MB_ICONINFORMATION); } else MessageBox("Devi specificare un cliente / numero di conto!", "Generatore di Password", MB_OK | MB_ICONSTOP); // Tutto a posto. Rimuovi l'expert. ExpertRemove(); return(INIT_SUCCEEDED); }
Ora facciamo una leggera modifica alla nostra funzione "Password_Check()" per restituire una stringa della password codificata. Ricorda di usare la stessa password in entrambe le funzioni Password_Check() e Password_Generate(). Puoi immaginare cosa succederebbe se non lo fai!
//+------------------------------------------------------------------+ //| Cripta le informazioni del cliente e restituisce la password //+------------------------------------------------------------------+ string Password_Generate(string client) { string MasterKey; uchar dst[], src[], key[]; // Definisci qui la tua chiave di crittografia. Deve essere di 7 caratteri per la crittografia DES/ECB // DEVE ESSERE LA STESSA PASSWORD DEFINITA NELLA FUNZIONE "Password_Check()"! // Rendila difficile da indovinare. Il tuo cognome non è una buona idea! // Qualcosa come "wLdU&$z" sarebbe buono. Per ora, useremo una semplice... MasterKey = "NotDemo"; // Converti MasterKey in array di caratteri StringToCharArray(MasterKey, key); // Cripta il cliente utilizzando la chiave DES StringToCharArray(client, src); CryptEncode(CRYPT_DES, src, key, dst); // Pulisci la chiave e codifica in BASE64 ArrayInitialize(key, 0x00); CryptEncode(CRYPT_BASE64, dst, key, src); // Restituisci la password crittografata return(CharArrayToString(src)); }
Ecco fatto, tutto qui. Inserisci le informazioni fornite dal tuo cliente e invia loro la password per email o con qualsiasi altro mezzo tu scelga. Naturalmente, il bello di questo è che puoi farlo dal tuo soggiorno a Bora Bora!
Come già detto, questo schema di sicurezza non richiede di ricompilare il tuo codice per ogni nuovo cliente né di codificare un host di validazione lato server, offrendo comunque una buona sicurezza per il tuo duro lavoro nel creare quel fantastico indicatore / Expert Advisor che hai realizzato!
Saluti!
-Claude.
Post correlati
- MQL5 Wizard: Creare Trading Signals con Morning/Evening Stars e MFI per MetaTrader 5
- MQL5 Wizard: Crea Trading Signals con 3 Corvi Neri/3 Soldati Bianchi e RSI
- MQL5 Wizard: Creare Trade Signals con Hammer/Hanging Man e RSI
- MQL5 Wizard: Strategia di Trading con Dark Cloud Cover/Piercing Line e RSI
- Utilizzare MQL5 Wizard per Trading con Dark Cloud Cover e Piercing Line