Ashmoreinc Ashmoreinc -4 years ago 115
Python Question

How to turn pickle output into an unreadable format

When using the pickle lib with some classes that i have created, the output is fairly easily readable to the user. For example, if i have a fill called saves, and save all my class data into a .save file inside it, when opening the file with a text editor, you can vaguely see all the variables and without too much struggle, change them to a desired result.

Heres a snippet from a save file i created with pickle (it's a game):

S'Strength'
p4
I5
sS'Health'
p8
I100


In this the value of 'Health' is 100 and the 'Strength' is 5, if the user was to edit the save file (as it will save locally), they could easily change any of the variables they'd like in order to cheat the game.

Because i am creating a game where saving the game is one of the features i plan to implement this has become an issue.

I did think about using encryption but using a second external lib is a last resort as it can be quite tedious, so i was wondering if there were any other ways i could go about doing this, or if pickle comes with a built in function for this (after researching i have not seen none).

Answer Source

Instead of trying to make your data unreadable, you could simply sign the data and then authenticate it when read.

Saving

Here use hmac to compute a hash. We then save the hash along with the data:

import hmac, pickle

# pickle the data
pickled = pickle.dumps(data)
digest =  hmac.new("some-shared-key", pickled, 
                   digestmod=<my choice of hasher>
                   ).hexdigest()

# now save the hashed digest and the pickled data
with open("some-file", "wb") as f:
    # save these in some way you can distinguish them when you read them
    print(digest, file=f)
    print(pickled, file=f)

Loading

To authenticate the data we recompute the digest of the pickled data and compare it against the digest saved alongside it.

import hmac, pickle

with open("some-file", "rb") as f:
    digest = f.readline()
    pickled = f.read()

# confirm integrity
recomputed = hmac.new("some-shared-key", pickle, 
                       digestmod=<my choice of hasher>
                      ).hexdigest()
if not compare_digest(digest, recomputed):
    raise SomeOneIsCheatingOhNoException
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download