复制保护静态库
我很快就会发布一个付费静态库,我想知道是否可以构建任何形式的复制保护以防止开发人员复制该库。
理想情况下,如果(且仅当!)该库被非法复制到开发人员的计算机上,我希望完全阻止该库链接到可执行文件中。这可能吗?
或者,如果链接到该库的非法副本的应用程序根本无法工作,这也是可以接受的。然而,非常重要的是,这不会给这些应用程序的用户带来任何负担(例如输入许可证密钥、使用加密狗,甚至需要互联网连接)。
该库是用 C++ 编写的,面向多种平台,包括 Windows 和 Mac。
我有什么选择吗?
I will soon be shipping a paid-for static library, and I am wondering if it is possible to build in any form of copy protection to prevent developers copying the library.
Ideally, I would like to prevent the library being linked into an executable at all, if (and only if!) the library has been illegitimately copied onto the developer's machine. Is this possible?
Alternatively, it might be acceptable if applications linked to an illegitimate copy of the library simply didn't work; however, it is very important that this places no burden on the users of these applications (such as inputting a license key, using a dongle, or even requiring an Internet connection).
The library is written in C++ and targets a number of platforms including Windows and Mac.
Do I have any options?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我同意其他答案,即万无一失的保护根本不可能。然而,作为一个温和的推动...
如果您的库是预编译的,您可以通过在 API 中要求自定义许可证信息来阻止过度非法使用。
将函数更改为:
第
一个参数标识客户,第二个参数是 MD5 或第一个参数的其他 哈希 以及 盐。
购买您的库后,您需要向客户提供这两个参数。
需要明确的是,对于足够聪明和雄心勃勃的人来说,这是一种很容易避免的保护措施。将此视为盗版道路上的减速带。这可能会让潜在客户相信购买您的软件是最简单的途径。
I agree with other answers that a fool-proof protection is simply impossible. However, as a gentle nudge...
If your library is precompiled, you could discourage excessive illegitimate use by requiring custom license info in the API.
Change a function like:
to:
Where the first parameter identifies the customer, and the second parameter is an MD5 or other hash of the first parameter with a salt.
When your library is purchased, you would supply both of those parameters to the customer.
To be clear, this is an an easily-averted protection for someone smart and ambitious enough. Consider this a speed bump on the path to piracy. This may convince potential customers that purchasing your software is the easiest path forward.
C++ 静态库是一个非常糟糕的可再发行版本。
它与机器人无关,但在我看来应该在这里提及。有许多编译器选项需要与调用者匹配:
最多有 64 种配置!
此外,即使您的 C++ 代码是平台无关的,它们也不能跨平台移植 - 它们甚至可能无法与同一平台上的未来编译器版本一起使用! LTCG 创建巨大 .lib 文件。因此,即使您可以省略一些选择,您也拥有巨大的构建和发行规模,以及为用户提供的通用 PITA。
这是我不会考虑购买仅附带静态库的任何东西的主要原因,更不用说添加任何类型的复制保护的东西了。
实现思路
我想不出比 Shmoopty 的建议更好的基本机制了。
您还可以为您的构建添加“水印”,这样,如果您检测到“野外”的库,您就可以确定将该库卖给了谁。 (但是,您要做什么?向可能无辜的客户写愤怒的电子邮件?)此外,这需要一些努力,使用易于定位的字节序列而不影响执行不会有太大帮助。
您需要保护自己免受 LIB“解包”工具的侵害。但是,链接器仍然应该能够删除未使用的函数。
总体思路
实施一个像样的保护机制需要非常谨慎和一定的创造力,而且我还没有看到任何一个机制不会产生额外的支持成本并且需要艰难的社会决策。在版权保护上花费的每一个小时都没有用来改进您的产品。 C++ 代码的市场并不是很大,我看到您的客户必须支付很多工作费用。
当我购买代码时,我很乐意为文档、支持、源代码和其他“面向未来”的标志付费。没有那么多的许可。
A C++ static library is a terribly bad redistributable.
It's a bot tangential, but IMO should be mentioned here. There are many compiler options that need to match the caller:
That's up to 64 configurations!
Also they are not portable across platforms even if your C++ code is platform independent - they might not even work with a future compiler version on the same platform! LTCG creates huge .lib files. So even if you can omit some of the choices, you have a huge build and distribution size, and a general PITA for the user.
That's the main reason I wouldn't consider buying anything that comes with static libraries only, much less somethign that adds copy protection of any sort.
Implementation ideas
I can't think of any better fundamental mechanism than Shmoopty's suggestion.
You can additionally "watermark" your builds, so that if you detect a library "in the wild", you can determine whom you sold that one to. (However, what are you going to do? Write angry e-mails to an potentially innocent customer?) Also, this requires some effort, using an easily locatable sequence of bytes not affecting execution won't help much.
You need to protect yourself agains LIB "unpacker" tools. However, the linker should still be able to remove unused functions.
General thoughts
Implementing a decent protection mechanism takes great care and some creativity, and I haven't yet seen a single one that does not create additional support cost and requires tough social decisions. Every hour spent on copy protection is an hour not spent improving your product. The market for C++ code isn't exactly huge, I see a lot of work that your customers have to pay for.
When I buy code, I happily pay for documentation, support, source code and other signs of "future proofness". Not so much for licencing.
您如何确定您的库在链接时是否被“非法复制”?
请记住,当链接器完成工作时,您的任何代码都不会运行。
因此,鉴于您的代码均未运行,我们无法在编译或链接时执行任何操作。这就需要尝试确定该库是否从完全不相关的目标机器非法复制到链接机器上。即使您愿意向最终用户施加“需要互联网访问”等负担,我仍然没有看到任何方法可以区分这两种情况。
我的结论是,模糊棒棒糖提出的“让东西变得非常有用,以至于人们想要购买它”的建议是“复制保护”代码库的最佳方式。
How would you determine whether your library has been "illegitimately copied" at link time?
Remembering that none of your code is running when the linker does its work.
So, given that none of your code is running, we can't do anything at compile or link time. That leaves trying to determine whether the library was illegitimately copied onto the linking machine, from a completely unrelated target machine. And I'm still not seeing any way of making the two situations distinguishable, even if you were willing to impose burdens like "requires internet access" on the end-user.
My conclusion is that fuzzy lollipop's suggestion of "make something so useful that people want to buy it" is the best way to "copy-protect" your code library.
复制保护,在这种情况下,执行保护的定义“给用户带来了负担”。没有办法解决这个问题。最好的版权保护形式是写一些有用的东西,让人们觉得有必要购买它。
copy protection and in this case, execution protection by definition "places a burden on the user". no way to get around that. best form of copy protection is write something so useful people feel compelled to buy it.
你不能做你想做的事(完美的复制保护,除了非法复制作品的人之外,不会给任何人带来任何负担)。
您无法在链接时使用标准链接器运行代码,因此无法确定此时是否正常。
这就留下了运行时,这意味着要求最终用户以某种方式进行验证,而您已经确定这是不可能的。
您唯一的选择是:按原样发布并希望开发人员不要复制太多,或者编写自己的链接器并尝试让人们使用它(以防万一它不明显:这是行不通的。头脑清醒的开发人员不会购买需要特殊链接器的库)。
You can't do what you want (perfect copy protection that places no burden on anyone except the people illegally copying the work).
There's no way for you to run code at link time with the standard linkers, so there's no way to determine at that point whether you're OK or not.
That leaves run-time, and that would mean requiring the end-users to validate somehow, which you've already determined is a non-starter.
Your only options are: ship it as-is and hope developers don't copy it too much, OR write your own linker and try to get people to use that (just in case it isn't obvious: That's not going to work. No developer in their right mind is going to buy a library that requires a special linker).
如果您计划发布一个昂贵的框架,您可以考虑使用 FLEXlm。
我与它们没有关系,但在各种昂贵的框架中看到过它,这些框架通常针对 Silicon Graphics 硬件。
If you are planning to publish an expensive framework you might look into using FLEXlm.
I'm not associated with them but have seen it in various expensive frameworks often targeted Silicon Graphics hardware.
几个想法...(这些有一些主要缺点,但应该是显而易见的)
在编译时:将库文件放在共享上,并仅向您的开发人员授予它文件权限已经把它卖给了。
在运行时:将库编译为仅在某些机器上运行,例如。检查 UID 或 MAC id 等
A couple ideas... (these have some major draw backs though which should be obvious)
For at compile time: put the library file on a share, and give it file permissions only for the developers you've sold it to.
For at run time: compile the library to work only on certain machines, eg. check the UIDs or MAC ids or something
您的问题的正确答案是:在证明您需要它之前,不要担心复制保护。
您说您“很快就会成为”运送付费静态库。”除非您证明有人愿意窃取您的技术,否则实施复制保护是无关紧要的。 “有人会偷它”的不安感觉并不能证明它会被偷。
创业最困难的部分是创造人们愿意付费的产品。您尚未证明您已经做到了这一点;因此复制保护是无关紧要的。
我并不是说你的产品没有价值。我是说,除非你尝试卖掉它,否则你不会知道它是否有价值。
然后,即使你卖了,你也不知道是否有人偷。
这就是成为一名优秀的程序员和成为一名优秀的企业主之间的区别。
首先,证明有人想窃取你的产品。然后,如果有人想窃取它,请添加复制保护并不断改进您的产品。
The correct answer to your question is: don't bother with copy protection until you prove that you need it.
You say that you are "soon to be shipping a paid-for static library." Unless you have proven that you have people who are willing to steal your technology, implementing copy protection is irrelevant. An uneasy feeling that "there are people out there who will steal it" is not proof it will be stolen.
The hardest part of starting up a business is creating a product people will pay for. You have not yet proven that you have done that; ergo copy protection is irrelevant.
I'm not saying that your product has no value. I am saying that until you try to sell it, you will not know whether it has value or not.
And then, even if you do sell it, you will not know whether people steal it or not.
This is the difference between being a good programmer and being a good business owner.
First, prove that someone wants to steal your product. Then, if someone wants to steal it, add copy protection and keep improving your product.
我只做过一次。这就是我使用的方法。这远非万无一失,但我觉得这是一个很好的妥协。它类似于德鲁·多尔曼的答案。
我建议提供一个初始化例程,要求用户提供他们的电子邮件和链接到该电子邮件的密钥。然后找到一种方法,让使用该产品的任何人都可以查看电子邮件信息。
我在为 AfterEffects 编写插件时使用的库上使用了此方法。初始化例程构建插件的“关于”对话框中显示的消息,并且我使该消息显示给定的电子邮件。
在我看来,这种方法的优点是:
客户不太可能传递他们的电子邮件和密钥,因为他们不希望他们的电子邮件与他们没有编写的产品相关联。
他们可以通过注册一次性电子邮件来规避此问题,但随后他们不会收到与他们编写的产品相关联的电子邮件,因此这似乎不太可能。
如果带有一次性电子邮件的版本被分发,那么人们可能会尝试它,然后决定他们想要使用它,但需要与他们的电子邮件关联的版本,因此可能会购买副本。免费广告。您甚至可能希望自己执行此操作。
我还想确保当我向公司提供插件时,他们不能根据我多年的专业知识将我的库提供给他们的内部程序员自己编写插件。为此,我还将插件名称链接到密钥。因此,密钥仅适用于特定的插件名称和开发人员电子邮件。
为了扩展德鲁的答案 - 为此,您需要在用户注册时获取用户的电子邮件,在末尾标记一组秘密字符,然后对其进行散列。您向用户提供哈希值。秘密字符集对于所有用户来说都是相同的,并且为您的图书馆所知,但电子邮件使哈希值变得唯一。当用户使用电子邮件和哈希值初始化库时,您的库会附加字符、对其进行哈希值并根据用户提供的哈希值检查结果。这样您就不需要为每个用户进行自定义构建。
最后,我觉得任何比这更复杂的事情都是徒劳的,因为真正想破解我的图书馆的人可能会比我更擅长捍卫它。这种方法只是阻止一个偶然的盗版者轻易拿走我的图书馆。
I have only done this once. This was the method I used. It is far from foolproof, but I felt it was a good compromise. It is similar to the answer of Drew Dorman.
I would suggest providing an initialisation routine that requires the user to provide their email and a key linked to that email. Then have a way that anyone using the product can view the email information.
I used this method on a library that I use when writing plugins for AfterEffects. The initialisation routine builds the message shown in the "About" dialog for the plugin, and I made this message display the given email.
The advantages of this method in my eyes are:
A client is unlikely to pass on their email and key because they don't want their email associated with products they didn't write.
They could circumvent this by signing up with a burner email, but then they don't get their email associated with products they do write, so again this seems unlikely.
If a version with a burner email gets distributed then people might try it, then decide they want to use it, but need a version associated to their email so might buy a copy. Free advertising. You may even wish to do this yourself.
I also wanted to ensure that when I provide plugins to a company, they can't give my library to their internal programmers to write plugins themselves, based on my years of expertise. To do this I also linked the plugin name to the key. So a key will only work for a specific plugin name and developer email.
To expand on Drew's answer - to do this you take the users email when they sign up, you tag a secret set of characters on the end and then hash it. You give the user the hash. The secret set of characters is the same for all users and is known to your library, but the email makes the hash unique. When a user initialises the library with their email and the hash, your library appends the characters, hashes it and checks the result against the hash the user provided. This way you do not need a custom build for every user.
In the end I felt anything more complex than this would be futile as someone who really wanted to crack my library would probably be better at it than I would be at defending it. This method just stops a casual pirater from easily taking my library.