Saving game score locally on iOS device...is security needed?
Do I need to store the score with a hash, ie to protect it from being edited/cheated by a user? From my newb knowledge, the user is unable to view and manipulate this locally stored data, as plist files for example. Can anyone elaborate?
[Edit] I'm storing scores locally and periodically uploading them to Game Center leader开发者_C百科boards. Even if the device is jailbroken I'd like to have security to prevent scores being manipulated by the user. What is a good approach?
I actually would do this:
Save it in an NSDictionary
and convert it to an NSData
object. Now comes the cool part:
Encrypt it into AES using this class:
https://web.archive.org/web/20160806074714/http://iphonedevelopment.blogspot.com/2009/02/strong-encryption-for-cocoa-cocoa-touch.html
This is a military standard encryption which will return an encrypted NSData
object. Then just save it to file and read/write whenever necessary. I've had really good experiences with this class and the user can't do anything to it.
Much better than just storing it in plain sight using NSUserDefaults
.
Give it a go!
I'm also new to iPhone programming - just built my first small game and am currently adding Game Center feature to the next version (called Smiley Lines ;) I believe many would be in the same situation as me - just want some simple hashing so jailbroken folks won't easily modify the score in user defaults, hence preventing messing up the online leaderboard.
If so, I find the NSData conversion to AES solution quite complicated (for an iOS newbie and for a simple need of hashing an integer) and bit overkill. After some search, a great solution is found here: Matthias Plapper has subclassed the NSUserDefaults class to provide some simple hashing with a secret key. Super easy to use - copy paste the two sources files and here's an example usage:
// Configuring user defaults. It is recommended that you do this
// immediately after the app did launch.
[NSUserDefaults setSecret:@"shh, this is secret!"];
// Write secure user defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setSecureBool:YES forKey:@"IsRegistered"];
// Read secure user defaults
BOOL valid = NO;
BOOL registered = [defaults secureBoolForKey:@"IsRegistered" valid:&valid];
if (!valid) {
// the property has been modified, handle this situation
} else {
// Valid property, do whatever you need to do
}
Thanks a ton Matthias!
In theory, the user can't manipulate this stored data.
However, there are methods to access the whole filesystem, so people could open your game's folder, edit the plist and modify their scores.
Personally, if I was making a game without online leaderboards, I wouldn't worry about it. Let them have the score they want, as long as other players aren't affected by it.
You can encode the scores with your own salt value and decode when required. This will prevent the user from simply changing the number that they see.
I have developed many iOS games, and I just save the local scores by either:
- Using the NSUserDefaults class, or
- Writing them directly to a local config file (e.g., .txt, .plist, etc.).
Technically, other apps can't touch the files inside your app's bundle, so you don't have to worry about them being edited.
精彩评论