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. 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?
Use an 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.
Related
The app that I'm developing allows the user to enter in a zip code, then the app displays my local businesses that are closest to them. So if someone entered in a New York zip code, all of my franchises located in NY would show up.
It would be ideal if I could see what zip codes are most popular with the usage of this app, and which states receive the most traffic.
Is there a way to record/analyze the entered in zip codes of my users, and have that data sent back to me? Will this become a privacy issue if I gather this data?
Thanks
EDIT
The zip code the user will enter is simply in an EditText.
What you want to do is certainly possible. Since you're posing this question at all, I'm guessing you're app has the available franchises stored locally as opposed to retrieving them from a server.
Where is the data supposed to be sent to? If you have a server, you can use an HttpsURLConnection and POST the requested zipcode to your server when the user presses calculate or however else calculation is kicked off in your app. You will need the internet permission for this to work.
As a word of caution, you should be very up front about that you're doing this to the user, and also give them an option to turn it off, or even have it turned off per default. Personally, this would be the kind of thing that would bother me a great deal if I were to use your app. (Actually, if I couldn't turn it off, I probably wouldn't use it.)
EDIT
I'm not an expert on U.S. privacy laws but I imagine you probably need a formal privacy statement, as well. You certainly do if your app is also available in the European Union (regardless of whether it's useful there or not - whether or not it's available is enough.)
Yes you can easily collect this data and return it to a server. This will require an additional permission for your application 'android.permission.INTERNET' (If not already included.)
Not a lawyer and didn't stay in a Holiday Inn... but I don't see a privacy concern if you're using anonymous data... if you're packaging up user information (Name, Phone #, etc.) and sending it back I would think you'd want to include a "privacy policy" in your app's terms of service.
I'm looking to install an android app on a set of tablets for internal company use. These tablets will be used in the field and I want the password to expire after 30 days and switch to a pre-determined (but random seeming) password every 30 days. I'd like that password to be unique for every tablet/install of the app. I will be installing the apps myself on each tablet before distribution.
I looked at various OTP schemes but couldn't find one that would work without requiring to connect to a server. To be honest, I've never done anything like this before and was a bit overwhelmed. Most of these tablets will not have access to internet while in the field and I'd like to be able to have users call in to get the next password after 30 days.
So ideally there's a pre-determined sequence of pseudo random numbers for each device, the user is given the password for this month and after 30 days, they have to call in to get the password for the current month for their specific tablet.
Hope this makes sense.
Thanks
Alright, I'll stream a couple of ideas I have about how you would achieve this.
My first thought when reading this was "You can do all of this through interacting with a Server, and frankly it would be easy with that support" until, of course, you noted that this wasn't possible.
I am making these suggestions under a few assumptions:
No one from your company is going to try to exploit the app in any way - like overbuffering or changing the apps language or utf settings etc etc. Also they won't try to look at any of the source files.
You will always get your hands on the devices before the people in your company use them.
Alright then, the handling of the 30-day predicament: The easiest way (though also most error prone way) would be to the get the systems current time (and date) when the user logs in, and set that "day" as counter "30 or "0." This can be done with Time now = new Time();
now.setToNow(); or Calendar c = Calendar.getInstance();. Store this "day" in your own SharedPreferences or just the DefaultSharedPreferences. Every time the app starts check this day with your current day, and calculate how many days it's been. If the current amount of days is 30 or greater, reset the password.
^This was one of the most simple, and also very "error...full?" (Couldn't think of a good word) ways to solve this. Now on to the passwords:
I would recommend using UUID for the passwords. Although the identifiers made aren't "technically" unique, the chances of getting the same password twice are...well so close to zero in your case it's probably not going to happen.
Generate these and store, lets say 1000 different ones into a file onto each device (a simple text file with each password on a different line will work), and save a copy in your own records (Make sure you know which passwords go to which device).
Then when that calendar counter from earlier goes off, set the password for the app as the "next" password in the file, deleting previous one from the file. The company employee calls you with his app Id (Generate an app ID the user can see in each app. So the first person who gets his app has app #1, the second is app#2 etc. so that you know which password file you should be reading from) you can send him the new password.
These are two veeeeeerrrryyy simple ways to handle this, but they might be able to at least get you thinking. Hope I helped a bit.
I have seven virtual products in my game and would like to give one away each day or so to people who visit my website.
Bob Smith is correct that this will work, but depending on the value of these in-app-purchases you may want to err towards something more complex.
If there's nothing generated about these codes, i.e. my code is the same as yours, then any one person can just give this code away and it will work for everyone. Another suggestion to keep in mind is to make the code a hash of some predetermined secret value, and the unique identifier of the app.
For example, if every app has in it an ID, your code might be:
md5(userId.toString + mySecret);
Because a hash is one way, nobody can get your secret back out and compute their own codes. They have to submit their app code through your service to get a code specific for them.
You can continue to layer in features too. You could include secret identifiers for each purchase, so that one algorithm generates unique codes for each purchase.
Of course, if there is only one secret, it would also have to be hard coded into the app, which is not utterly secure. This is a problem for both Bob's system and mine, and should that secret get public the entire system falls apart. You could look into all sorts of different encryption techniques to come up with more and more clever systems, if you need that level of security.
Yes you can do that, what you should do is send the recipient of the code the code via email or someway, then in the app have a spot where the person can enter the code in. Similar to entering in cheat codes in a videogame. If their code they enter matches one that you made valid, you should grant them access to the virtual product.
I've figured I have to do some kind of API where the Android app sends parameters to a php-file, or similar.
I'm thinking of an app that would have some sort of high score list. How would I go about making sure that the submitted high score values are in fact achieved through the app? Say that the person achieves 9001 points. Now if this only results in some sort of file.php?score=9001 call, I'm not feeling very secure about people finding the php-location and submitting whatever they like.
Any input on this kind of problem? Thank you.
There is no way to make this 100% secure since you have no way of verifying where a request came from, but there is a way to make it slightly harder to hack the highscores. It's still basically security through obscurity but it requires digging in to the actual app binary rather than just looking at the network connections.
First, pick a "password" for your app. Instead of sending just the score, also send a cryptographic hash (say, SHA-256 or something) of the password concatenated with the score. On the server side, recalculate the hash of password concatenated with score and check if this matches the submitted hash. If it does not, reject the score submission.
Now this is somewhat more secure than the initial approach because looking at the requests the app makes does not enable you to forge scores. However, looking in to the binary code off the app will still allow an attacker to recover the password and forge score submissions, but this is very involved and probably good enough for your purposes.
Of course, this does not rule out being able to duplicate a score (once the proper hash is known, you can submit a score as many times as you want). If you even want to prevent this, submitting a score would have to go like this: request (random) ID number from server, hash score + ID + password, submit the score + hash, the server then checks whether this hash is good. The server needs to remember the ID number so this is a little more involved to program.
A simpler solution would be to associate each score with the players name, and only allow 1 score per player. Then you could hash password + name + score.
Good afternoon!
It's better to communicate with the server via POST. So you can send an additional parameter, e.g. key, from your app to server and check it there.
The sample of PHP:
<?
$key = trim(htmlspecialchars($_POST['KEY']));
if ($key == 'your_secret_string') {
//write data to DB
}
?>
This question already has answers here:
Creating an Android trial application that expires after a fixed time period
(13 answers)
Closed 9 years ago.
My android application should work only for 1 month after its release. What to do for that?
Please see this question, it has a good answer.
I will give you my experience with trials. At first I tried just using the date on the phone, but then realized if they uninstall and re-install this can be bypassed. This could be fixed by storing the install date somewhere on the file system (hidden), but what happens if the user wipes data or finds the file?
I also tried to just check the date/time at a server anywhere (maybe your www site?), but this imposes restrictions on your application because they must have internet. Soon I realized the need for better license management, so the last solution was used.
The last solution would be to setup a server. You can use the device's unique ID (whichever you choose - I went with the Bluetooth MAC ID because my application requires bluetooth as well), post to a server to check if the user has a trial, if they don't I issue them one, if they do I check the expiration. Now I have complete control over when trials expire. Since my application is a business app that is used in the field, this is very handy if a potential buyer needs another week.
The only issue with the last solution is that if you plan on publishing to Market, you must use their payment system.
Good luck!
Just to add a bit more code-related as well:
Use SharedPreferences to store the date on first-start up
Get the date at every start up - you can use for exampe Date.currentTimeMillis() - and calculate if 1 month has passed
Check current date and calculate expiration date.
That should be pretty easy, just read the date on the first start-up and store it, then compare the date for every subsequent start-up with the stored date, if its greater that x days, pop-up a message box saying the app has expired.
Or am I missing something ?
/Tony
Use alarm Reciever instead, and broadcast when it gets expired.
http://developer.android.com/reference/android/app/AlarmManager.html,
here is a tutorial TOO.. http://moazzam-khan.com/blog/?p=157
if you are worried about the data on the device(and you should! unless you encrypt it) you can save the data on a server and retrieve it on each start up.
On the other hand if application crackers worries you, dalvik byte code today is easily reversed using dedexter or smali and with apktools and jarsigner you can actually find the place where the protection is change some jumps, fill the rest of the code with nops to keep it aligned and resign it uploading it to some crackers market where they share it. So it wont help you too much.
You can make life hard for them if you obfuscate your code with proguard, but it will slow them down,wont stop them.
If your app is web based, meaning the user will need to obtain server data from you, create a key for the registered users that will be received from the server (you can base it on their private details + IMEI) and verify your requests with it, if you get wrong\no key from the client reject the request.
It's not 100% proof either since requests could be faked and someone could grab someone else's IMEI and key and face all the requests.
welcome to broken software copy protection world :-)