我正在用Python开发一款软件,它将分发给我雇主的客户。我的雇主想用一个有时间限制的许可证文件来限制软件的使用。
如果我们分发.py文件甚至.pyc文件,将很容易(反编译和)删除检查许可证文件的代码。
另一个方面是,我的雇主不希望我们的客户读到代码,担心代码可能被窃取,或者至少是“新颖的想法”。
有什么好办法来解决这个问题吗?
我正在用Python开发一款软件,它将分发给我雇主的客户。我的雇主想用一个有时间限制的许可证文件来限制软件的使用。
如果我们分发.py文件甚至.pyc文件,将很容易(反编译和)删除检查许可证文件的代码。
另一个方面是,我的雇主不希望我们的客户读到代码,担心代码可能被窃取,或者至少是“新颖的想法”。
有什么好办法来解决这个问题吗?
当前回答
你的雇主是否意识到他可以“偷”回其他人从你的代码中得到的任何想法?如果他们能读懂你的作品,你也能读懂他们的。也许看看你如何能从这种情况中受益,会比担心你可能会失去多少,获得更好的投资回报。
[编辑]回答尼克的评论:
没有得到也没有失去。客户得到了他想要的东西(因为他自己进行了更改,所以已经为此付费了)。因为他没有发布变更,就好像它没有发生在其他人身上一样。
现在如果客户出售软件,他们必须更改版权声明(这是非法的,所以你可以起诉并且会赢->简单的案件)。
如果他们不更改版权声明,第二级客户就会注意到软件来自您的原创,并想知道发生了什么。很有可能他们会联系你,这样你就会了解到你的作品被转售的情况。
同样,我们有两种情况:原来的客户只卖了几份。这意味着他们并没有赚到多少钱,所以为什么要麻烦呢。或者是销量。这意味着你有更好的机会了解他们的工作,并为此做些什么。
But in the end, most companies try to comply to the law (once their reputation is ruined, it's much harder to do business). So they will not steal your work but work with you to improve it. So if you include the source (with a license that protects you from simple reselling), chances are that they will simply push back changes they made since that will make sure the change is in the next version and they don't have to maintain it. That's win-win: You get changes and they can make the change themselves if they really, desperately need it even if you're unwilling to include it in the official release.
其他回答
不要依赖混淆。正如你的正确结论,它提供的保护非常有限。 更新:这里有一个论文的链接,它在Dropbox中逆向工程混淆的python代码。操作码重映射方法是一个很好的障碍,但显然它是可以被击败的。
相反,正如许多海报所提到的那样:
不值得花时间进行逆向工程(你的软件这么好,花钱是有意义的) 如果可行的话,让他们签订合同并进行许可证审核。
或者,就像强大的Python IDE WingIDE所做的那样:放弃代码。没错,把代码送出去,让人们回来进行升级和支持。
我很惊讶,在任何回答中都没有看到“具体”。也许是因为它比问题更新?
它可能正是你所需要的。
它不会混淆代码,而是在加载时对代码进行加密和解密。
来自pypi页面:
保护python脚本工作流程 Your_script.py导入pyconcrete Pyconcrete将钩子导入模块 当你的脚本导入MODULE, pyconcrete导入钩子将尝试查找MODULE。先撒,再撒 解密模块。Pye via _pyconcrete。Pyd并执行解密的数据(如 .pyc内容) 加密和解密_pyconcrete.pyd中的密钥记录 (如DLL或SO)的秘密密钥将隐藏在二进制代码,不能 直接在HEX视图中看到它
用同样的方法保护c/c++的二进制文件,即对可执行文件或库二进制文件中的每个函数体进行混淆,在每个函数项的开头插入指令“跳转”,跳转到特定的函数来恢复混淆的代码。字节码是Python脚本的二进制代码,所以
首先编译python脚本代码对象 然后迭代每个代码对象,将每个代码对象的co_code混淆如下所示
0 JUMP_ABSOLUTE n = 3 + len(bytecode) 3 ... ... Here it's obfuscated bytecode ... n LOAD_GLOBAL ? (__pyarmor__) n+3 CALL_FUNCTION 0 n+6 POP_TOP n+7 JUMP_ABSOLUTE 0
将混淆的代码对象保存为.pyc或.pyo文件
那些模糊的文件(。Pyc或.pyo)可以被普通的python解释器使用,当这些代码对象第一次被调用时
First op is JUMP_ABSOLUTE, it will jump to offset n At offset n, the instruction is to call a PyCFunction. This function will restore those obfuscated bytecode between offset 3 and n, and put the original byte-code at offset 0. The obfuscated code can be got by the following code char *obfucated_bytecode; Py_ssize_t len; PyFrameObject* frame = PyEval_GetFrame(); PyCodeObject *f_code = frame->f_code; PyObject *co_code = f_code->co_code; PyBytes_AsStringAndSize(co_code, &obfucated_bytecode, &len) After this function returns, the last instruction is to jump to offset 0. The really byte-code now is executed.
有一个工具Pyarmor可以通过这种方式混淆python脚本。
我记录了如何通过将其转换为.so文件和将其转换为python轮文件来混淆python: https://github.com/UM-NLP/python-obfuscation
如果我们关注软件许可,我建议看看我在这里写的另一个Stack Overflow答案,以获得如何构建许可密钥验证系统的灵感。
GitHub上有一个开源库,可以帮助您进行许可证验证。
你可以通过pip安装许可来安装它,然后添加以下代码:
pubKey = "<RSAKeyValue><Modulus>sGbvxwdlDbqFXOMlVUnAF5ew0t0WpPW7rFpI5jHQOFkht/326dvh7t74RYeMpjy357NljouhpTLA3a6idnn4j6c3jmPWBkjZndGsPL4Bqm+fwE48nKpGPjkj4q/yzT4tHXBTyvaBjA8bVoCTnu+LiC4XEaLZRThGzIn5KQXKCigg6tQRy0GXE13XYFVz/x1mjFbT9/7dS8p85n8BuwlY5JvuBIQkKhuCNFfrUxBWyu87CFnXWjIupCD2VO/GbxaCvzrRjLZjAngLCMtZbYBALksqGPgTUN7ZM24XbPWyLtKPaXF2i4XRR9u6eTj5BfnLbKAU5PIVfjIS+vNYYogteQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"
res = Key.activate(token="WyIyNTU1IiwiRjdZZTB4RmtuTVcrQlNqcSszbmFMMHB3aWFJTlBsWW1Mbm9raVFyRyJd",\
rsa_pub_key=pubKey,\
product_id=3349, key="ICVLD-VVSZR-ZTICT-YKGXL", machine_code=Helpers.GetMachineCode())
if res[0] == None not Helpers.IsOnRightMachine(res[0]):
print("An error occured: {0}".format(res[1]))
else:
print("Success")
你可以在这里阅读更多关于RSA公钥等配置方式的信息。