Developing for Software Protection and Licensing
Last updated 2009-10-26.
When writing a non-free application, it's best to think about software licensing and protection from the outset. Too many teams leave licensing until the last moment, and then find it's difficult to integrate with the product.
We recommend the following approach to licensing:
- Correctly prioritise licensing during development
- Use a third party licensing system
- Use an obfuscator
- Don't rely on Code Access Security
- Be WET, not DRY
- Be nice to your users
1. Correctly prioritise licensing during development
Licensing is a vital feature of non-free software. If you are dependant upon revenues from your software, then you should be thinking in terms of maximising those revenues from the outset.
In addition, a well-considered licensing strategy can aid market segmentation. Licensing individual features of a product can give you a range of products to target all segments of your market. You may be able to offer a 'light' version of your product at a reduced price, or restrict high-end features of your products to premium versions.
A flexible licensing solution should also allow you to offer your customers subscription based licensing - an option that is cheaper than outright licence purchase but that expires after a specified period.
Thus it's vital that you determine your licensing requirements early. In an Agile environment, customers often neglect licensing, electing to deprioritise licensing stories in favour of other functionality.
You should encourage your customers to ask: what good is the application without the ability to distribute it in a manner that will earn you money?
It takes us around four minutes to integrate a basic application with OffByZero Cobalt; that's time very well spent.
Prioritising licensing means that you need to prioritise your installer as well. If you're building software that must be deployed but doesn't yet have an installer, the value of the features in that software is precisely zero. On Agile projects with a deployment requirement, we encourage customers to prioritise basic installer functionality (including licensing integration) very highly.
Often the product of the first iteration is an application skeleton, an installer, and basic licensing. This also allows for automated deployment testing at a very early stage, and allows testers to help developers streamline the licensing and deployment process.
2. Use a third party licensing system
Designing a software licensing system from the ground up is hard. You must take into account a wide range of requirements including security, stability, flexibility and opacity.
Then, once built, there is an ongoing maintenance cost both in terms of the code, and in terms of infrastructure. You must administer the server or servers upon which the software runs, provide integration end-points for automatic purchasing of licences, and comprehensively test the entire system.
We believe that most companies would be better served by buying a high-quality third-party licensing system. This approach will free your developers to work on core functionality, and will alleviate maintenance and support costs. It also allows you to take advantage of the domain expertise offered by licensing specialists, and avoid releasing software that is easy to crack.
Another advantage to buying a third-party solution is that you can quickly and easily evaluate it for suitability; with an in-house system you have to pay in advance for the development of a system that may not prove adequate for your needs. Choosing an high-quality third party system dramatically reduces the risk involved in developing a solution in-house.
3. Use an obfuscator
If you are developing in .NET or Java, shipping a non-obfuscated application is almost equivalent to shipping in source code form. If you're concerned about intellectual property within your code (especially if you're interfacing with devices in a fashion that might expose trade secrets) then you need to use a quality obfuscator.
It is vital that you test your licensing solution post-obfuscation, for two reasons.
Firstly, obfuscators tinker with many aspects of the code (e.g. in .NET properties are removed) and you need to be certain that your software licensing solution is not broken by this.
Secondly, you need to be certain that obfuscation actually obfuscates your licensing API. If you can use a tool like Reflector and see that your code contains references to something like
LicensingApi.IsLicenceValid() then crackers are going to find it very easy to break your licensing logic.
On Java, we use and recommend Proguard.
It's important to note that no software protection solution can be guaranteed to be 100% unbreakable; fundamentally, once your binary is on another machine, you have relinquished complete control of it. The aim should be to use a high-quality software licensing system in conjunction with obfuscation to make it very hard & time-consuming to crack your software, thereby raising the bar sufficiently high to protect your revenues.
4. Don't rely on Code Access Security
If you are using .NET, and relying upon Code Access Security to prevent people from tampering with your licensing assembly, be aware that there is now a tool which makes breaking CAS trivial.
Our article titled CAS Tamper-Proofing is Broken: Consequences for Software Licensing has more details, but what it boils down to is that you need to compile your licensing code directly into your application rather than referencing it in separate assemblies.
OffByZero Cobalt provides the components you need to integrate with your application in source code form, so you can do just that.
5. Be WET, not DRY
Software licensing is a notable exception to the DRY (Don't Repeat Yourself) practice - software licensing code should be as WET (We Enjoy Typing - the opposite of DRY) as possible.
If you isolate your licensing logic in one place, separated from other concerns, you make it far easier to modify your software to disable the licensing altogether. It is much better to repeat the licensing logic many times throughout the application, preferably such that it is executed numerous times throughout a single execution of the software.
For example, we suggest that you perform a licensing check during installation, during application startup, and whenever important features are accessed. Don't check the licence once during startup & pass that value around; instead, actually replicate the licensing check in each area. It's inconvenient, but far better than releasing a product that's easy to crack.
Furthermore, try to embed the licensing code within the implementation of particular features. For example, if you have a feature that involves saving files, you should check the licence during the save operation, rather than before. This makes it even harder for crackers to identify licensing code.
Of course, it is important that your licensing solution doesn't slow the application down too much during these checks. Your automated UI tests should include some tests to measure the performance of the application with licensing enabled, comparing that performance against acceptable minima. We have designed OffByZero Cobalt to allow multiple licence checks with minimal impact upon application performance.
6. Be nice to your users
Software licensing should make life significantly harder for unauthorised users of your software; it shouldn't have any significant impact upon your legitimate user base. To this end, your licensing solution should not control your application. Instead, it should present information on licence status through an API, thus allowing you to decide how your application will respond.
To encourage upgrades, your licensing solution should allow for real-time updates to licences. E.g. a customer should be able to pay you to enable a particular feature on your software without re-issuing licences, or worse, actually having to reinstall your software. It should just be a matter of checking a box on a form, and then having your application pick up the change the next time it contacts the server.
You should allow for the widest range of usage scenarios. If your application is needlessly restrictive, users will be provided with an incentive to crack your licensing system even if they are authorised to use your product.
Your licensing solution should provide for a range of scenarios including concurrent user licensing and even passive monitoring (where execution is never prevented, and the licensing code is merely used to gather usage data).
Even small enterprises nowadays use Terminal Services, Citrix™ and virtualisation; if your licensing solution can't handle deployment to those environments you risk losing both customers and reputation.
Of course, OffByZero Cobalt handles all of the above scenarios with ease.