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 编译器:在安装过程中保护软件的重新分发的主要内容,如果未能解决你的问题,请参考以下文章

C语言编译器” MinGW-w64 C/C++”的安装

Virbox LM 软件加密保护

matlab2011b在安装激活过程中出现问题

在 MATLAB 中识别 VC++ 编译器

matlab回调函数生成.exe文件好处

MATLAB 编译器的代码文件寻址