Reputation: 359
I am designing the licensing part of my application. It will using something like JWT from my licensing server to issue claims that my code running on workstations will use to enable functionality.
The server will sign the claim with its private key, and the client will use the public key to verify the signature. As it currently stands this will be done in .NET with C#.
If an attacker can replace my server's public key with their own, they can set up a fake server to issue licensing claims and enable functionality they are not entitled to.
What steps can I take to make it hard for an attacker to find and substitute a public key in C#?
Specifically, should I use and trust as robust an obfuscation library?
I recognise no protection is absolute. If I allow my code to be run on a machine I do not control, then with enough skill, motivation and resources an attacker will be able to recover the data. I will settle for making it hard enough for moderately skilled individuals with the resources of a person or a small corporation.
One of the open source obfuscators available that I plan to investigate is ConfuserEx.
Edit:
Some responders think I've got the issue around the wrong way. I respectfully disagree. The issue is a little analogous to an attacker adding their own certificate to a browser's certificate score, and setting up their own rogue banking banking site that fools the browser.
However the analogy fails here. The issue is not the classical one of PKI, "how does the end user's (trusted) client verify trust in the server", but more that of DRM in a semi-hostile environment. The risk under consideration is not loss of confidentiality or integrity for the user, but of control of where, when and how the core application is run.
Up until now I hadn't been thinking in terms of DRM, but I think that is the best description, and I admit that doesn't sit well with me. DRM generally has a negative user impact and requires massive effort from the developer/provider, and still ends up broken, sometimes trivially.
Still, I feel the original question still stands, as I want to take reasonable steps to protect my work.
Upvotes: 5
Views: 1719
Reputation: 9228
You could investigate signing your PEs with Authenticode. This is an type of signing that is recognized by Windows and is completely separate to .Net strong names. You'd use SignTool to sign your assembly with something along the lines of:
signtool.exe sign /f mycert.pfx /p pfxpassword /t "http://timestamp.verisign.com/scripts/timstamp.dll" /d "my app" /du "http://mywebsite.com" "C:\path\to\assembly.dll"
You can then extract the Authenticode public key at run-time and validate against this.
The advantage here is that you are leveraging the current PKI to protect your application - someone would need to purchase a Verisign certificate and distribute the entire certificate (including the private key), resulting in Verisign likely revoking their certificate and causing the "keygen" to cease working on the next CRL update.
Obviously, someone could still decompile your application to MSIL and remove the check entirely - obfuscation won't prevent this and learning MSIL is trivial for anyone who can apply themselves. You simply can't prevent piracy at the software level, you can only deter it. I wouldn't bother hiding a public key as your current system is a fantastic deterrent.
If you want to annoy customers and deter crackers you can investigate a hardware key.
Upvotes: 3
Reputation: 1852
There are lots of questions raised by your question and without meaning offence, your question implies that you should get someone else to design or build the licensing part (or buy one off-the-shelf).
The problem is not the public key, it is the private key. The private key signs the claim, the public key only verifies it. You then start talking about a fake licensing server which does not seem to relate to the original concern about someone stealing a public key since a fake server could return anything. If somebody is going to create a fake server, then they are likely to be able to bypass the licensing check in the client software and not need the server or keys at all.
Obsfucation is nowhere near security, it is a delay at best and the fact that you ask the question shows that you do not have enough experience to be designing this.
As you say, as soon as the software is on an uncontrolled machine, you cannot stop an attacker bypassing the protection, the more useful question is who is likely to attack it, how much they might gain from it and whether it would be worth their time. If it is high value, use a hardware-dongle to lock the software down, these are produced by people who understand how to create secure locks and will be the best protection you can probably offer. You should also consider how you can change things over time to make it a moving target.
Upvotes: 1
Reputation: 17402
Obfuscation is a good layer of protection, but still does not not add a foolproof method to protecting your keys. There are many programs out there where the code can be deobfuscated and decompiled. See de4dot and dotPeek.
I would recommend obfuscating your code-base, but also putting the key in an un-managed C++ dll (Win32 project). Even though it's still technically possible to get the key from, it's much harder IMO than obfuscated .NET code.
Edit:
As /u Scorpion has mentioned, the value will still be constant in the C++ library. You can go a step further and encrypt the key using AES.
Upvotes: 1
Reputation: 793
A public key is supposed to be, well, public. If you're worried about an attacker replacing the key in your application and hosting their own license server, then protecting a key is pretty much a distraction from the actual issue: your local licensing solution won't work.
Just imagine if you did obfuscate or encrypt the key's value somehow: even if the key was secure, an attacker who would be able to edit it and reverse engineer a license server would just as easily disable the check in your application's functionality that prevents them from using unlicensed features!
Upvotes: 2