¿La mejor manera de guardar valores en el disco y evitar alteraciones? (Sin encriptación over-the-top)

I am programming a game, and I want highscores to be able to be saved locally, but I dont want the user to be able to go into a plist file and change the values. What is the best way to make it difficult for users to edit the highscores easily. Would making the value an NSNumber that I then write as NSData be sufficient?

preguntado el 27 de agosto de 11 a las 19:08

Even if you write the number to a plain text file, it will be difficult for users to edit the highscore. App files aren't user accessible, at least not without some effort. -

Right, but if the user has a jailbroken phone it becomes exceedingly easy if the score is saved as plaintext. -

This is true. I've done this myself :) -

5 Respuestas

AES is probably more trouble than it's worth here. Much as I respect Jeff LaMarche, this implementation is not good. It's adequate for this purpose, but it's not something to copy around in my opinion unless you understand what's right and what's wrong with it. I talk about this at length in Cifrar correctamente con AES con CommonCrypto and include how to do AES correctly; but you probably don't want the hassle of doing AES correctly here, and it wouldn't buy you much if you did.

My recommendation is a simple checksum hash:

- (NSUInteger)checksumForScore:(NSUInteger)score player:(GKPlayer *)player {
  NSString *string = [NSString stringWithFormat:@"%d%@%@", score, [player playerID], kLongRandomPassword];
  return [string hash];
}

You then store the checksum along with the score. You validate it like:

- (BOOL)isValidChecksum:(NSUInteger)checksum forScore:(NSUInteger)score player:(GKPlayer *)player {
  return (checksum == [checksumForScore:score player:player]);
}

He usado GKPlayer playerID here to pick something that's easy for you to use, but not trivial for the device owner to change while playing. Doing it this way makes replay attack hard. I can't just copy my friend's plist entry with it's super-highscore to my plist. It's also nicely persistent when the user changes devices or restores this device. If you're not using GameKit, first, you probably should :D and second, you'll have to figure out if there's some other key you want to use. A "user handle" would be fine too if you have the user enter that at some point. Anything that's unique-enough to the user that he wouldn't just copy his friend's.

Keychain is interesting as an obfuscation technique. It's a royal pain to read even legitimately, so the official SDK provides its own obfuscation :D I doubt it's worth the trouble, but it is a decent place to "hide" small amounts of data.

NSCoding isn't even obfuscation. Anyone who's going to bother to open up the plist can read and write NSCoding in less than a minute. Same for turning this into an NSData. Same for storing it in SQLite or Core Data.

@CocoaFu's suggestion of NSDataWritingFileProtectionComplete is clever, but I doubt it will have any real impact on a jailbroken device. Once the device is unlocked, the OS will will decrypt any file for you, so it's no barrier at all to someone who knows the device's PIN.

Respondido 28 ago 11, 00:08

Save the data with NSData built-in encryption:

- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)mask error:(NSError **)errorPtr

with the option:

NSDataWritingFileProtectionComplete

Disponible en iOS 4.0 y posterior.

Respondido 27 ago 11, 23:08

I don't believe this will have any impact on a jailbroken device (which is the only device this is a concern for). Since the device is unlocked, the OS will decrypt the data for you. Have you seen a different behavior that would make this more useful in this case? - Rob Napier

How would a user edit a plist? They would have to jailbreak to get access to the documents folder of your app. Even if I wrote an app to try to access your plist, the sandbox prevents me unless the device is jailbroken. I wouldn't worry about this for a game score and spend my time elsewhere.

Respondido 27 ago 11, 23:08

There is a Mac application PhoneView that provides GUI access to app data. Not that I don't disagree about the waste of time. - zaph

"Not that I don't disagree"? I assume you meant: "Not that I disagree". <g> - Rudy Velthuis

Ah, interesting, maybe they access the backup files on the Mac? - progrmr

If you are really concerned, you code encrypt the data. Aquí es un tutorial sobre cómo hacerlo.

Creo que NSCoding is probably the easiest bet though. It formats the save file in a non-obvious way, and you would have to know what you are doing in order to change it.

Espero que ayude!

Respondido 27 ago 11, 23:08

Mira aquí también:

1) Keychain services http://developer.apple.com/library/ios/documentation/Security/Conceptual/keychainServConcepts/iPhoneTasks/iPhoneTasks.html

2) or save data in sqlite db using CoreData.

Respondido 27 ago 11, 23:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.