Algorithm: Stop invalid entries into a Competition in python script
Question: I have an Android Mobile App that is really just a calendar & you can click a
certain date & a secret code pops up. The user uses that code to enter a
competition - they follow the link to the competition HTML page(python script
really) & enter their details to enter the competition. There are 100 minor
prizes & 3 major prizes. A code can either be a non-winning code or it can win
the user a prize(either the minor or major).

So they will be redirected to: <http://mycompetition.com/comp.py?code=ABCDEF>

Then they enter their age, code & image captcha(avoiding spammers) & click
enter competition.

**My Problem:** I am having difficulty coming up with an algorithm to ensure
that people just don't type in the above URL & put a random code value for the
CGI 'code' value & accidentally win a prize if they guess a correct code(or
they use a bot to keep trying).

**Can you come up with any ideas to avoid someone who has not purchased the
app just going to the url above & typing in a random code & accidently winning
the prize?**

My algorithms/ideas:  
\- Have the code 12 characters long which makes the probability of guessing
the code very slim but still possible. I am bad with maths & probability so if
I use 26 char & 10 digits as potential chars in the code does that mean the
probability of guesing correct 1 out of (36 chars * 12 pass length * 103
prizes)? Does that probability leave only supercomputers(not that I believe
anyones going to devote a super computer to my comp :P) able to guess the
code?  
\- Dont associate a prize with a code. Instead just have the android app
randomly generate some code that means nothing & when they enter the
competition I just give them a random 1/10000 (I dont expect anywhere near
10000 entries into the comp) of winning a prize. To enter the competition you
have to enter your age & the code & then enter a captcha to avoid spammers.  
\- Is there any easier algorithm you know of that avoids users who haven't
purchased the app getting a prize?

**EDIT:** \- What about whenever the App is downloaded I look at their
phones(wireless part) MAC address. On 1st run of the app I upload that MAC
address to my server that contains a list of MAC addresses of users of my app.
When/If they discover the secret code, they clikc enter competition & are
redirected to
[http://mycompetition.com/comp.py?code=RANDOMMEANINGLESSGENERATEDCODE&uniqueID=USERSMACADDRESS](http://mycompetition.com/comp.py?code=RANDOMMEANINGLESSGENERATEDCODE&uniqueID=USERSMACADDRESS).
In my script I check that the uniqueID is in my list of users who downloaded
my app, if it isn't I dont proceed, if it is they have 1/10000 chance of
winning a prize. Can you see any flaws in this algorithm?


Answer: Use an [HMAC](http://en.wikipedia.org/wiki/Hmac) to generate the code based on
a secret you share between the Android app and the site. As the text for the
HMAC, you can use a random value, which you include in the resulting code, or
something unique to the user, such as their email address (meaning that each
user can only have one valid code). If the length of the code is important,
you can truncate the hash produced by the HMAC, but bear in mind that the
shorter you truncate it, the more practical a brute-force attack is.

As long as your users cannot discover the shared secret, this will be secure
insofar as an attacker would have to guess at random, or attempt to determine
the secret by brute force. Since the code runs on user-owned devices, though,
there's no way to prevent them from extracting the code from your app. A user
with a rooted phone and a disassembler could do this relatively easily. To
combat that, you could obfuscate the code, and release new versions of the
app, updating the secret key there and on the site, whenever you suspect it's
been compromised.

Ultimately, because the device is in the user's control, there's no way to
totally prevent users from generating their own codes, but using an approach
such as the one above, you can make it much more difficult for them, and
easier for you to recover from it.

