Matlab 编译器:在安装过程中保护软件的重新分发
Posted
技术标签:
【中文标题】Matlab 编译器:在安装过程中保护软件的重新分发【英文标题】:Matlab Compiler: protecting re-distribution of software during installation 【发布时间】:2018-05-11 08:59:54 【问题描述】:我正在考虑使用 Matlab Compiler 来分发软件以收取一定的费用。我正在研究(非常)简单的方法来劝阻重新分发而不会惹恼用户。有什么建议吗?
一种想法是通过电子邮件向用户发送许可证密钥,并让他们在安装过程中输入该密钥,以便在许可证服务器上进行验证。如果密钥与服务器上的密钥匹配,则安装照常进行,否则,将显示警告消息,通知用户购买另一个许可证。但是,此方法要求指定功能仅在安装过程中运行,之后不再运行(以免打扰用户)。是否可以使用 Matlab 编译器或其他方式?
我想我可以在用户的磁盘上创建一个程序在启动时查找的文件(如果它存在,那么它不是第一次运行),但如果用户复制整个目录,则该文件也会被复制。
【问题讨论】:
一种方法是将用户的系统 UID 硬编码到已编译的可再发行组件中。您必须为每个客户端进行编译,这取决于您的用户群有多大,如果可行的话。对于很多用户,我会寻找真正的许可解决方案,例如 FlexLM。不知道有没有免费的。 这是获取唯一 ID 的一种方法:***.com/a/820549/7328782 查看How to add license/key to .exe generated with Matlab Compiler 以获得一些建议。 【参考方案1】:为了创建有效的许可系统,您必须将其链接到用户计算机的一个或多个属性(MAC 地址、操作系统 ID、硬盘序列号、CPU 序列号等...)。
如果您不这样做,您只会发布可以从一个用户转移到另一个用户的许可证。如果一个用户决定将他的许可文件传播到世界各地,那么您注定要失败,因为每个人都可能会获取该许可文件并使用它来解锁您的应用程序。
但是,如果您将许可证文件链接到用户计算机的一个或多个属性,如上所述,您必须能够获得这些属性:
-
在用户决定购买您的应用程序之前;
当用户激活他的许可证时。
第一个场景
您将软件作为试用版发布。当它第一次启动时,您在注册表或隐藏在某处的文件中设置到期日期。您在应用程序启动时检查到期日期,一旦到期,您就会抛出错误,并且您不再让使用过的人与您的应用程序一起玩。
在应用程序中,您可以在某处创建一个Register Now
按钮。单击它时,应用程序检索机器属性并将它们传递到将打开的网页/表单以让用户执行付款。该页面将负责验证机器属性、接收付款,最后根据这些属性提供有效的许可证代码。
在应用程序中,您必须实现允许表单创建许可代码的相同逻辑,因为每次启动应用程序时您都需要使用它们来验证代码本身。一个伪代码示例:
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lc = GetLicenseCode();
if (~strcmp(sha1([mp1 mp2 mp3]),lc))
errordlg('Invalid license code!');
return;
end
这是最简单的路径。但请记住,如果用户机器的一个或多个属性发生变化(因为他更改了设备或重新安装了他的操作系统),他的许可证将失效,您必须提供处理这种情况的客户协助服务.
第二种情况
这个难度要大得多。您将无法提前知道用户的机器属性。因此,您的许可系统将分两步运行。当用户购买您的应用程序时,您会发布一个唯一代码(例如称为LID
)。然后,一旦用户将其插入到您的应用程序中,您的应用程序必须将其与机器属性一起发送回。然后计算最终密钥(例如称为LKey
)并将其发送回用户。
mp1 = GetMachineProperty1();
mp2 = GetMachineProperty2();
mp3 = GetMachineProperty3();
lkey = GetLicenseKey();
if (~strcmp(sha1([mp1 mp2 mp3]),lkey))
errordlg('Invalid license code!');
return;
end
机器属性
第一个解决方案已通过注释提供给您:位于注册表项HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
中的MachineGuid
值。它很结实。但它只适用于 Windows 机器。使用winqueryreg
访问注册表。
另一个不错的选择是Window Domain Controller Security ID
,它是另一个特定于机器的唯一标识符。您可以在 Matlab 中使用Java
代码检索它:
wdc_sid = com.sun.security.auth.module.NTSystem.getDomainSID();
或通过 Windows 注册表项 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\GroupMembership
。如果您想与旧的 Matlab 版本保持一定的向后兼容性,则应该使用注册表方法。不幸的是,Window Domain Controller Security ID
是另一个仅在 Windows 下运行的机器上可用的标识符。
如果您想让您的许可系统适应所有可能的操作系统和环境,您必须使用一种更通用的方法,该方法基于普遍可访问的硬件属性:MAC 地址、硬盘序列等。据我所知,最可靠的属性是MAC地址,因为它的唯一性,虽然没有被授予,但几乎可以肯定,而且更换网络适配器的频率非常低(实际上损坏硬盘的机会更多)。使用Java
代码获取机器网卡的MAC地址,如下:
mac_addrs = '';
net_int = java.net.NetworkInterface.getNetworkInterfaces();
while (net_int.hasMoreElements)
mac_addr = net_int.nextElement.getHardwareAddress();
if (~isempty(mac_addr))
mac_addrs = [mac_addrs, '-', sprintf('%.2X',typecast(mac_addr,'uint8'))];
end
end
mac_addrs = mac_addrs(2:end);
上面的计算产生了一个字符数组,表示机器上找到的所有 MAC 地址的串联结果。同样,出于兼容性原因,这可能不适用于旧的 Matlab 版本,因此您必须使用更复杂的方法,如 here 所述。
[编辑]
这种基于底层操作系统检索 MAC 地址的方法可能更容易:
switch computer('arch')
case 'maci','maci64'
[~,a]=system('ifconfig');
c=strfind(a,'en0');if ~isempty(c),a=a(c:end);end
c=strfind(a,'en1');if ~isempty(c),a=a(1:c-1);end
% find the mac address
b=strfind(a,'ether');
mac_add=a(1,b(1)+6:b(1)+22);
case 'win32','win64'
[~,a]=system('getmac');b=strfind(a,'=');
mac_add=a(b(end)+1:b(end)+19);
case 'glnx86','glnxa64'
[~,a]=system('ifconfig');b=strfind(a,'Ether');
mac_add=a(1,b(1)+17:b(1)+33);
otherwise,mac_add=[];
end
我在this article的cmets中找到了。
【讨论】:
谢谢@TommasoBelluzzo,~strcmp(sha1([mp1 mp2 mp3]),lkey)
中的sha1
是什么?我在 Matlab 的文档中找不到它。或者,它是什么东西的伪代码?
这是伪代码。实际上sha1
是一种散列算法。它通常以字符串形式使用。这就是为什么我将潜在密钥与各种机器属性的 sha1 进行比较。为了在 Matlab 上计算它,我认为你必须使用 Java 代码......尝试在谷歌搜索它,你会找到一些结果。以上是关于Matlab 编译器:在安装过程中保护软件的重新分发的主要内容,如果未能解决你的问题,请参考以下文章