-1

I have made a game in python which generates quite a large number of highscores which I want to store, with preference for security, storage efficiency and ease of use. At the moment I am storing them in a dictionary, with keys that refer to the different level types, which is then written to a .txt file and retrieved using eval.
EDIT: I am now aware this is a bad idea and am using json instead. However the file is still legible, and any encryption that could be added would be beneficial.

import os

#Reading from file
try:
    with open(os.path.join(root_directory, 'highscores.txt'), 'r') as f:
        highscores = eval(f.read())
except IOError:
    highscores = dict()

#Writing to file
with open(os.path.join(root_directory, 'highscores.txt'), 'w') as f:
    f.write(highscores)

However, there a few issues I have with this method that I would like to get some advice on.

  • I want to reduce the file size. Compressing the file does make a big difference, but any more efficient formats would be preferable.
  • I would like to make it a bit more secure. Ideally I would want it to be hard for a player who is familiar with python to be able to work out how to edit the highscores.
  • I would like to make it easier to update a master copy of the highscores with new additions to distributed copies, in particular the use of tuple keys in the dictionary is rather clumsy.

Would it be worthwhile making a Highscore class which would make use of serialize and deserialize methods, and is there any additional security which could/should be added to this?

Siwel
  • 705
  • 10
  • 25
  • What is the result file size? – Reut Sharabani Aug 12 '15 at 23:16
  • 1
    Use JSON. Not `pickle`, not `eval()` on a dict in a .txt file; JSON :). – Cyphase Aug 12 '15 at 23:18
  • I'd take a look here for a bit more information (though not encryption): http://stackoverflow.com/questions/28326725/a-user-score-saving-program/28326996#28326996 – Reut Sharabani Aug 12 '15 at 23:18
  • @ReutSharabani Currently only about 500kB, however that is with relatively little game-play, and I would expect it to grow significantly. I am also looking to store more game data. – Siwel Aug 12 '15 at 23:19
  • @Cyphase why do you recommend JSON, which of the features I'm looking for would you say it offers particularly? – Siwel Aug 12 '15 at 23:20
  • 1
    this is exactly what stuff like postgres,redis,mongodb,mysql,etc were created for... – Joran Beasley Aug 12 '15 at 23:22
  • Can you give us an estimate of the size of your game's playerbase? – TigerhawkT3 Aug 12 '15 at 23:23
  • 1
    @Siwel `json` is more secure(and faster if you use `simplejson`) ... if I made my username `os.system("format C:")` and you run your `eval` on that you might not like the outcome – Joran Beasley Aug 12 '15 at 23:24
  • @JoranBeasley Thanks for that point, I was aware it was not something to keep! I currently only have a few friends playing it, but am looking to make it available online. – Siwel Aug 12 '15 at 23:26
  • if you want to define your own serialization YAML is like json, but you can define your own object types (you could also use pycrypto to encrypt/decrypt as part of the serialization) – Joran Beasley Aug 12 '15 at 23:27
  • Anyone want to comment on why the downvote? – Siwel Aug 26 '15 at 14:52

2 Answers2

1

JSON would be a good format to store your scores in. If you're concerned about file size, you could gzip the JSON file, though that could have an impact on performance.

If your users have access to the source code, I doubt there's a good way to encrypt the file that couldn't be undone with a careful examination of the code. If it's "compiled" into a less source friendly format, then you could probably do some encryption, though the key would be in there somewhere.

JSON and gzip seem to be part of a standard python install, while there are a couple of seemingly well regarded encryption libs, like Simple-Crypt and Crypto which would need to be installed.

However, if you may have multiple processes possibly updating this file (e.g. multiple players playing simultaneously), you could run into collisions resulting in a corrupted file. As others have suggested here, some sort of database would be a better solution.

OldGeeksGuide
  • 2,888
  • 13
  • 23
  • I use `py2exe`, so the source code shouldn't be easily available. I'm not hugely concerned about security at the moment, but a basic level of it would be good. – Siwel Aug 12 '15 at 23:33
  • if you want it decentralized you should really look at postgres or something ... (but then you'll need a server) – Joran Beasley Aug 12 '15 at 23:34
  • HDF5 storage is an option. It's compressed, can be accessed in parallel with MPI (http://mpi4py.scipy.org/docs/usrman/index.html) and remotely with OPeNDAP (http://hdfeos.org/software/hdf5_handler.php), available on many platforms , portable and sharable. A Python API for it is provided by the h5py package (http://www.h5py.org/). The O'Reilly book "Python and HDF5" by Andrew Collette gives additional documentation of this API. The HDF5 project website is https://www.hdfgroup.org/HDF5/. –  Aug 13 '15 at 00:03
  • 1
    What encryption modules are part of a standard python install? – martineau Aug 13 '15 at 00:58
  • It looks like I was slightly mistaken on that. I took these - https://docs.python.org/2/library/crypto.html - to be encryption/decryption, but they seem to be just hash functions. But it looks like Crypto or Simple-Crypt are good possibilities. I've updated my answer to reflect this. – OldGeeksGuide Aug 13 '15 at 17:58
1

As suggested in the comments, JSON does seem to be ideal storage method for your project. Below is a modified version of your code which has been modified to read & write JSON to your highscores.txt file.

import os
import json

#Reading from file
try:
    with open(os.path.join(root_directory, 'highscores.txt'), 'r') as f:
        highscores = json.load(f)
except IOError:
    highscores = dict()

#Writing to file
with open(os.path.join(root_directory, 'highscores.txt'), 'w') as f:
    json.dump(highscores, f)

Regarding security, to write to the text-file you would probably want to encode the highscores into JSON; encrypt the JSON'd data; write the encrypted JSON'd data to the text file. To then read this data, simply reverse what we just did in the order we did it. If you search around, you will come across multiple useful cryptography libraries that Python has to offer. Best of luck!

Braden1996
  • 108
  • 1
  • 7