Software protection and serial numbers


#1

I,m looking for a cross platform solution to create a demo version of our juce application that can be activated/unlocked with a unique serial number.

All the big boys seem to be using PACE InterLok pro. And this does look good but i was wondering if anyone here has any experience with InterLok or alternative systems.


#2

PACE is an object og hatred in the audio community. It works well in many cases, but since it works on the driver level it has the capacity to severly fuxxor a system, and does so from time to time judging by the testimonials. So if your target audience is in the amateur audio/music field I’d say don’t use PACE.

Thoughts:
Instead of a serial you might want to go with a key file. Lots more room. Then you can make a strong key.

Use a multiplexed key, which is to say many independent keys baked into one. Then test the different elements of the key at different places in the code.

Do a test in every non-time critical function in the code. If you make your tests in the form of inlinable functions in a globally accesible module it’s not too time consuming.

So you end up with many different looking test segments, spread all over the binary. That’s very time consuming to hack, and the multiplexed key makes it hard to make a keygen.

The point being that you can end up with hacks and key gens that seem to work, and the cracker has to test every function in the software in order to be sure. And if you make some tests inactive until a certain date it makes it even worse.

You want the cracking to be a dull repetetive task rather than out and out hard.

2 cents.


#3

Good suggestions there. For my stuff I use the juce crypto classes to encrypt the keyfile with a public/private key, so they can’t write a keygen without factoring the key, which is pretty much impossible.


#4

I guess it,s not a good idea to put code for doing this stuff in juce itself because anyone can then study it,s inner workings. But would it be possible to obtain a framework for this from you Jules?


#5

I wouldn’t worry about that. Any good cryptography geek can tell you that if a system relies on obscurity to stay secure, it’s not secure.

With a good public-key system, you can study the code as hard as you like, but you won’t get any closer to cracking the keys. That’s secure.


#6

[quote=“Rock Hardbuns”]
You want the cracking to be a dull repetetive task rather than out and out hard.[/quote]

Very true! Better a chore, than a challenge.


#7

I can’t really publish my system though, because the hard bit is building all the webserver code, to manage the user permissions, generate and send out keyfiles, etc. That’s all a bit of a nightmare. The bit of code that actually goes in your app is the easy bit!


#8

I’m responsible for the interface and website in our company and I have built our current system that generates and sends serials. But this is all based on Delphi for our old application.

We already have experience building the webserver stuff but we do not have any experience with building an encrypted, multiplexed key file in juce. So if you could publish a framewerk for doing that part we,d be very happy campers :wink:


#9

Making the keyfile’s actually really easy. I store all the info in my key as XML and use RSA to turn it into an encrypted hex string that you stick in the keyfile, like this:

[code]static const String encryptXml (const XmlElement* xml,
const String& rsaPrivateKey)
{
BitArray val;

if (xml != 0)
{
    const String s (xml->createDocument (String::empty, true));
    const MemoryBlock mb ((const char*) s, s.length());

    val.loadFromMemoryBlock (mb);
}

RSAKey key (rsaPrivateKey);
key.applyToValue (val);

return val.toString (16);

}

static XmlElement* decodeEncryptedXml (const String& hexData,
const String& rsaPublicKey)
{
if (hexData.isEmpty())
return 0;

BitArray val;
val.parseString (hexData, 16);

RSAKey key (rsaPublicKey);
key.applyToValue (val);

const MemoryBlock mb (val.toMemoryBlock());
XmlDocument doc (mb.toString());

XmlElement* const xml = doc.getDocumentElement();

#ifdef JUCE_DEBUG
if (xml != 0)
{
DBG (xml->createDocument (String::empty, true));
}
#endif

return xml;

}[/code]


#10

ok nice.

I guess part of what should be stored in this key should be something that identifies the computer like the network adapter’s MAC address using SystemStats::getMACAddresses, but surely that will not be enough?

Sorry for the newby questions but we have absolutely no experience with writing this or a serial generating (and validating) algorithms.


#11

Yes, that’s the general idea. You could stick in other info like customer details and the version of the application, etc.


#12

So if i understand correctly; the keyfile does not contain a serial number that is checked by the application?


#13

Up to you, really. I put a machine number in there. You could use a serial number if you want.


#14

I’d say to do that too. Actually, I’d say make the key file consist of several different encrypted blocks that are dealt with in different places.

Here’s how I think of it.

If the semi pro heavy weight cracker teams decide to do your app, you don’t have a snowballs chance in hell of stopping them. But there are not too many of those fellas and they tend to go for big brand expensive apps.
And even then good scheme will delay them.

The rest of the crackers are 16 year olds looking for some street cred (or IRC cred I guess), and as such they have a limited attention span and want quick payoffs to their cracking endevours.

Cracking usually means using dissassemblers and low level debugging tools like softICE. With these you can follow a programs execution and for example see when the file is accessed and what is done with it.

So you want to avoid having a single point of failure on the binary level so to speak, because the cracker will find it and remove it. This means that what ever you can decentralize, you should.

So perhaps you could have one key segment with the user details, and another with a checksum of the same and so on. What ever you can make up basically.

You want the cracker to have to get stuck in a terribly boring debug-reassemble-test cycle.


#15

Has anybody worked with outside vendors like Kagi for this sort of thing? That’s what I’m thinking of doing, because I certainly don’t relish making my own system for that stuff.


#16

Thank you for your advise!

Found some interesting articles on wikipedia:


But so far I have not found any decent info about writing a serial number algorithm so any pointers on that would be welcome :wink:


#17

I’ve been looking at the Raw Material store and the PPMulator before jumping in and building my own storefront, software activation infrastructure, etc. As this thread is a little old now, I’m wondering if there is any new web products that might reduce the amount of work I need to do. Or for that matter, I’m wondering if Jules can share any lessons learned from putting his infrastructure together. Jules - anything you would do differently today. I like your storefront a lot. Seems to be no nonsense, and all of the boundary conditions (no internet access, lost passwords, etc) seem to be addressed.


#18

Yes, it seems to work pretty well, though it was incredibly tedious to write it all, especially the web-server side of things!

The only thing about my site is that although I tried hard to make it as simple as I could, people still get confused about where they go to buy something… Not sure whose fault that is!


#19

Yep the web server side is a pain, especially as I need to migrate from a static site to a dynamic one and don’t have Apache, mySQL, or PHP running locally (yet). There is a lot of useful information in this thread.

Using an RSA encoded keyfile sounds like just the ticket. And the advice to check early, check often, regardless of how or what you check is key.

I’m wondering if I should store my ‘keyfile’ as a real file, or stuff it in the registry. Anybody have real-world experience that indicates one approach is less prone to problems and hassles than the other?


#20

As a developer who has implemented software licensing (and have had them cracked), you can’t really prevent your software from being cracked by them finding and bytezapping your license tests, no matter how clever or spread they are. The crackers use tools like SoftIce which make this actually quite easy… they can find where the key gets put into memory, and run your program, and have the debugger stop at any instruction that accesses that memory. Boom, they just found one of your tests and they can no-op it with a byte zap. Even if you put in 20 seperate tests in 20 locations, they can find them all through this trick in minutes. (Yes, there’s a LOT you can do to make it harder, ranging from redundant decoy reads to the license info, to time-based decisions how to check, etc…)

Making your software uncrackable is a very very difficult job that I don’t think ANYONE has ever really succeeded with. Much more important for you though, you should put your priority on making your software un-keygen-able. A keygen is the real problem for developers. If your software is cracked, your next patch will have to be recracked and pirates will need to find and install the new crack… a hassle both for crackers and pirates. If there’s a keygen, pirates install and run your unmodified software directly, and your updates to the software will also work, and the cracker never has to do anything!

So, how do you prevent a keygen? The easiest way is with crypto, an RSA encoded key is pretty much The Answer, and not hard to do. The downside with RSA crypto is that the key will become too long to type, so you have to deal with license files or have your users do cut-and-paste of huge text strings. If you want your license code to be less than 50 typed digits, you have to do a lot (a real lot, a huge amount) more work to make the key encoding/decoding secure, mostly through tedious (not clever) obfuscication with the goal of boring the cracker.