加密在 MQL 程序中很少使用。 在日常交易中,使用密码术的机会并不多。 一个例外就是偏执的信号跟单机希望保护发送的数据免于监听,仅此而已。 若数据不会离开终端,很难想象为什么需要加密/解密数据。 甚至,这可能代表开发人员能力低下,因其造成了终端的额外负载。也许无需在交易中使用加密? 实际上,其实有。 例如,考虑许可。 可能会有一家小型公司,甚或一位广受欢迎产品的独立开发者。 这种情况与许可问题相关,因此需要许可证加密/解密。可在许可证中指定用户数据,和产品的可编辑列表。 指标或智能交易系统开始操作,检查许可证的可用性,及给定产品的期限。 程序向服务器发送请求,更新许可证,如有必要,或可接收新的许可证。 这可能不是最有效和最安全的方式,但出于演示目的,我们将在本文中运用它。 显然,在这种情况下,许可证将通过不同的软件工具进行读取/写入 — 终端,远程服务器,控制模块和日志记录模块。 它们可以由不同的人,在不同的时间,以不同的语言编写。本文的目的是研究加密/解密模式,在这种模式下,MetaTrader 终端可以解密由 C# 或 C++ 程序加密的对象,反之亦然。本文适用于中等技能的程序员和初学者。设定任务概述中已经提到了这一点。 我们将尝试模拟一个实际问题的解决方案,要求为若干种产品(指标和智能交易系统)的许可证创建、加密和解密。 对于我们而言,用哪个程序来加密和解密许可证并不重要。 例如,可以先在开发者的计算机上创建许可证,然后在销售部门对其进行纠正,然后在交易者的计算机上解密。 该过程必须针对性能低廉的算法有很强的容错性。除了解决主要任务外,我们还将研究许可的复杂问题。 这不是一切就绪立即可用的许可证,而只是可能的变体之一,应对其进一步进行编辑和开发。源数据我们参考终端文档来获取操作的源数据。 有两个标准函数负责加密/解密过程:int CryptEncode( ENUM_CRYPT_METHOD method, // conversion method const uchar& data[], // source array const uchar& key[], // encryption key uchar& result[] // destination array );int CryptDecode( ENUM_CRYPT_METHOD method, // conversion method const uchar& data[], // source array const uchar& key[], // encryption key uchar& result[] // destination array );开发操作对象鉴于我们研究如何将加密/解密应用于许可,故我们的操作对象是许可。 这应该是一些包含可适用在许可证的各种产品信息的结构。 这里需要以下数据:
% J6 r: w- D6 G3 H3 R5 M该产品的许可期限。
5 c) a" O, Z2 j" M9 R产品名称。* X' G3 \$ _+ _1 \$ H" b
我们用最简单的方法创建相应的结构:#define PRODMAXLENGTH 255struct ea_user { ea_user() {expired = -1;} datetime expired; //License expiration (-1 - unlimited) int namelength; //Product name length char uname[PRODMAXLENGTH]; //Product name void SetEAname(string name) { namelength = StringToCharArray(name, uname); } string GetEAname() { return CharArrayToString(uname, 0, namelength); } bool IsExpired() { if (expired == -1) return false; // NOT expired return expired <= TimeLocal(); } };//struct ea_user包含在用户描述结构中的信息:
! v. R3 n6 a9 N' W独有的用户 ID。 还可以保存名称,但每次都要发送个人数据(即使是加密形式)似乎并不可取。0 c7 ~0 q" t! @# }2 D
用户帐户上可用产品的有关信息。
7 G/ P( o! b3 F) M. X, e4 t. m, q用户的许可证到期日期。 该字段可限定所有现有产品的用法,甚至是无限制产品,作为用户服务时间。, Y( N/ r! u+ U6 Q+ C# g. c+ T
用户终端中许可产品的数量:2 F# _ ~1 I" u! M1 ~
#define COUNTACC 5struct user_lic { user_lic() { uid = -1; log_count = 0; ea_count = 0; expired = -1; ArrayFill(logins, 0, COUNTACC, 0); } long uid; //User ID datetime expired; //End of user service (-1 - unlimited) int log_count; //The number of the user's accounts long logins[COUNTACC]; //User's accounts int ea_count; //The number of licensed products bool AddLogin(long lg){ if (log_count >= COUNTACC) return false; logins[log_count++] = lg; return true; } long GetLogin(int num) { if (num >= log_count) return -1; return logins[num]; } bool IsExpired() { if (expired == -1) return false; // NOT expired return expired <= TimeLocal(); } };//struct user_lic |