53

I have finished developing an app for Android and intend to publish it with GPL -- I want it to be open source. However, the nature of the application (a game) is that it asks riddles and has the answers coded into the string resource. I can't publish the answers! I was told to look into storing passwords securely -- but I haven't found anything appropriate.

Is it possible to publish my source code with a string array hidden, encrypted, or otherwise obscured? Maybe by reading the answers from an online database?

Update

Yuval Filmus's solution below worked. When I first read it I was still not sure how to do it. I found some solutions, for the second option: storing the hashed solution in the source and calculating the hash everytime the user guesses. To do this in javascript there is the crypto-js library at http://code.google.com/p/crypto-js/. For Android, use the MessageDigest function. There is an application (on fdroid/github) called HashPass which does this.

David Richerby
  • 82,470
  • 26
  • 145
  • 239
Nevermore
  • 667
  • 1
  • 5
  • 9

6 Answers6

88

You have at least two options, depending on what problem you want to solve.

If you want innocent readers of your code to not get the answers inadvertently, or you at least want to make it a bit difficult so that users are not tempted, you can encrypt the solutions and store the key as part of your code, perhaps a result of some computation (to make it even more difficult).

If you want to prevent users from retrieving the answer, you can use a one-way function, or in computer jargon, a hash function. Store a hash of the answer, and they you can test whether the answer is correct without it being possible to deduce the answer at all without finding it first. This has the disadvantage that it is harder to check for an answer that is close to the correct answer, though there are some solutions even to this problem.

Yuval Filmus
  • 280,205
  • 27
  • 317
  • 514
29

You have two three options:

Keep the answers separate from the rest of the source code

If you want your code to be open source, however don't want the answers to be open source, then you open source the code for the application without the questions & answers, with the questions & answers being a separate closed source "plugin" or data file. Your Android app would bundle both of these together into a single app.

Put the answers in your source code

Alternatively, if you consider the questions and answers to be a core part of what you want open sourced then you should put the answers into the source code, preferably un-obfuscated so that others can read and modify them. Obfuscating source code so that it can't be understood and modified isn't really in keeping with the principles of open source code.

Put the answers on a server on the internet

With both of the above solutions it's possible for someone who has downloaded your app to find out the answers without playing your program in either case - no matter how you obfuscate / encrypt your answers, if your program can identify the answer without additional information, so can a human examining your compiled app.

If you really want to make sure that nobody can find out the answers then the only real option is not to give them the answers and have the app call a web service etc... whenever they want to know the answer. The app should send the answer that the user has entered and the web service should tell the app whether or not the answer is correct, that way the user has no way of telling what the answer is until after they already have the correct answer (short of brute-forcing the web service, which you can detect and protect against).

If you are looking for ways to obfuscate your answers the that suggests to me that you don't really want to open source your answers in the first place, so you should consider the first options.

If it's critical that the user not be able to find the answer in advance then the third option is your only real choice, however I'm struggling to think of a scenario where this would be worth the effort, not least because it prevents your users from using your app without an Internet connection.

Glorfindel
  • 754
  • 1
  • 9
  • 20
Justin
  • 391
  • 2
  • 8
4

If the object is to obscure strings from casual reading of the source code but keep them open so other people can easily make their own changes - for example if you were publishing the source to a text adventure and didn't want any descriptive text to appear which would constitute a spoiler, then use something reversible like rot13.

In fact, you could rot13 all your translation files and flip them back on the fly.

That's keeping the open spirit. Random "magic" hashes isn't really programmer-friendly.

moopet
  • 141
  • 3
4

Why would you store your answers in your GPL source code if you don't want your users to know them? Even if they're not known or easily crackable now, they can (and likely will) be in the future.

Instead of storing them in your app, use an external database. Make a small web service that compares the answers to what's in your database. Then let your application make a call to that webservice whenever it has to verify. The main problem is that, because it requires internet access, you will lose some speed and potential userbase. your app license should only apply for the app itself, not the webservice.

You could also just put your answers in a small database and put that in your program. As far as I know, GPL only applies to source code, not any data that your app stores. I might be wrong on that, though.

Nzall
  • 143
  • 3
3

Open source requires the source code to be made public and available, not the game data. So you could easily put the data in another file and not publish that one. Add some crypto if you want to prevent casual reading of the file. I doubt a strong crypto is necessary for your application.

liftarn
  • 139
  • 3
1

Remember that even if you store a database in a remote web server, the database can still be duplicated by simply writing down all correct key/value pairs that have been seen. And generally speaking, mobile apps should try to not give errors or cease to function because the network is down (use queued messaging, and "update when you can").

So if you want a local database, but don't like the idea of it getting blatantly decrypted, you can use a bloom filter (to avoid talking to a network or having a big decrypted database locally). This is how spell checkers used to work when memory space was really tight.

So, if you add question/answer pairs into the filter like:

Hash(NormalizeString(Question[n]))+Hash(NormalizeString(Answer[n]))

If you ask if "Capitol of Virginia?Richmond" is in the set, it will either answer "definitely no", or "almost certainly yes". If you get too many false positives, then make the database larger.

You could have an immense database in a tiny space, assuming that the user will spell the Question and Answer exactly as you expect. Keeping the database small helps with updates, because they probably have to be transferred over wireless networks.

Rob
  • 490
  • 2
  • 9