Thinking about offline product registration / authentication

Hi friends!

My first project is inching ever closer to completion, and I’ve started to brainstorm about the immense topic of product authentication/registration/unlocking. For my use case, I’m not concerned about making my software impossible to crack/pirate, I just want to make it “not easy”.

Now, I would really like to find a solution for this that requires no internet connection on the user’s machine at authentication-time, for several reasons:

  • I’m a beginning developer, and I can’t afford to spend money on a server at this time
  • I believe that using an internet connection to authenticate is a very large potential source of bugs, and frustration & confusion for paying customers, which is the last thing I want!
  • The moral and ethical implications of employing a server to run 24-7… but that’s really outside the scope of this forum post

So, with all of that in mind, I’ve been brainstorming on this question: is it possible to create a reasonably secure authentication system that does not require an internet connection?

I’m familiar with the obvious approach of hard-coding a list of acceptable keys into the binary, and giving each paying customer a key, and the authentication check is to see if the key the user enters is in the list. Personally I think this approach offers barely any security, and isn’t really worth doing at all – might as well just not use authentication.

The other approach I’ve been pondering would be something inspired by RSA-style public/private key cryptography…

If the auth check is putting the key through some kind of mathematical one-way function, then only the public key would need to be hard-coded into the project’s binary. When the user purchases the product, they recieve a private key. At authentication-time, when the user enters their key, the plugin would run both the user-entered private key and its hard-coded public key through the same one-way function, and authentication is only successful if both functions get the same answer.

One major benefit of this approach seems to be that it would allow the developer to generate new keys at will, without having to update the product itself in any way. And, of course, this would also eliminate the overhead cost of an authentication server.

Does this seem like a reasonable approach?

Are there still any obvious glaring security flaws in this basic design?

I’m very new to cryptography, and programming in general, so any insight is appreciated!

We’ve done that for Nexus1. It was cracked within three months. Also, you have to verify the key somewhere. It’s trivial for crackers to find that “if ( keyisValid () )” and skip it. Unless you plan to do something novel with the key (or its payload) you might as well not bother.

2 Likes

I’m a beginning developer, and I can’t afford to spend money on a server at this time

I wouldn’t overestimate the costs here. We use AWS and you can do quite a bit without leaving their free tier.

The moral and ethical implications of employing a server to run 24-7

You don’t need to get a dedicated box. A modern VPS that isn’t performing any work uses remarkably few resources, so I wouldn’t spend much time worrying about this! There are also function-as-a-service offerings that would allow you to only spin up servers when they are needed.

IMO you should not roll your own key auth unless you’re doing it as a hobby project, and should use an established service instead.

We’ve used LimeLM and have been perfectly happy with it. One of the selling points for us was offline activation, and it’s worked perfectly for us so far.

2 Likes

I see. So just out of curiosity, do you think it’s even theoretically possible for an offline solution to be acceptably secure?

what about having the keyIsValid() returning a variant, or enum or something, instead of a simple bool?

Thank you for the input! I’m seriously reconsidering this now.

Do you think that this:

is a valid point?

The offline method has no way of limiting the re-use of keys. So once one key is disclosed it can be used by everybody.

When you allow users to migrate to a new machine, they have to be able to authorize again. If you don’t have a server, this is your manual task. I think not to allow that is not an option, and I wouldn’t want to be called each time a user wants to install a new system.

I also was too worried, even though I had a pretty secure version going but not very tested. I ended up not to sell my plugin at all but let it rot in the archives. Shame actually.

I must admit the activation services I saw so far were all a bit too pricy for a beginner. They usually started with a minimum fee which was offputting for me.

Now that PACE owns Juce, I am hoping that they will assist in getting some of the basic iLok functionality provided natively as part of Juce or at least more directly supported. I realize the OP question was related to offline activation and authentication, but to me the iLok solution is pretty universally “accepted” and does not require any new authentication schemes to be developed. The “licensing” aspects of iLok could possibly be used without all the encryption and protection.

Startup costs for iLok are not necessarily practical for small developers or hobby projects, so I don’t think smaller devs even look at it. Hopefully, PACE will find a way to offer the Cloud iLok services at a nominal cost. I would certainly consider it.

I think activation in general is a potential point of frustration for users, since they just want to use the product they’ve signed up for or purchased. I don’t think activation being online or offline makes a ton of difference here – ultimately it comes down to the UX your provide in your app more than anything.
Covering the little things like “what happens when a user forgets their product key” goes a long way.

FWIW, despite the fact that we offer offline activation, the overwhelming majority of our users (>98%) activate online

2 Likes

You can use JWTs, there are plenty of libraries in various languages/frameworks for generating and validating them however you want. As others have said the overhead of a licensing server isn’t that bad.

My personal opinion is that piracy is an economics problem and economic solutions are the least evil. There are better ways to make money than making your software hard to use. But different products/markets will be more or less tolerant of licensing schemes so it’s not a one-size-fits-all approach.

FWIW getting your first licensing algorithm cracked is a good sign that you’re doing something right!

One issue with embedding a public key is that you can run into issues should you ever need to cycle keys. You don’t want to brick software with a backend update.

1 Like

Thanks everyone for the input!

This… is a great point. Damn.

I tend to agree. I’m beginning to lean towards just not bothering with authentication (or just doing the basic, hard-code a list of keys into the binary approach…)

This hits it on the head for me. I’d like to think that people who want to support me will buy my product. I’m seriously considering just forgoing any kind of “registration” altogether…

Unless the Base64 class in JUCE has changed, using JWT’s in JUCE requires a tiny bit of pre-processing to work with JUCE.

2 Likes

All my auth code is independent of JUCE so I haven’t hit that. Thanks for the heads up!

1 Like

This hits it on the head for me. I’d like to think that people who want to support me will buy my product. I’m seriously considering just forgoing any kind of “registration” altogether…

So to go against my own point - there are definitely good reasons to require licensing/authentication in some way! Like for example if you have even a small API on your web backend you may want all access to be authenticated (even if the users don’t have to pay for a license, having a signup + sign in check to get a valid token). For example if you have a big database of user presets you may not want any person/bot on the internet to trawl your endpoints and download files at will, your bandwidth costs might become non negligible.

Since I didn’t see you mention it here - have you checked out the RSA-based approach shown in this tutorial?

[JUCE: Tutorial: Unlock your plugins through online registration]

JUCE has an RSAKey class, and while it is pretty limited in scope, it will allow you to implement the keyfile system shown in that tuorial.