Search Unity

Hash to Encrypt Local Data

Discussion in 'Scripting' started by fulviodedalord, Jun 15, 2018.

  1. fulviodedalord

    fulviodedalord

    Joined:
    Apr 16, 2018
    Posts:
    2
    Hi guys, I need to encrypt the data that I store locally to prevent hacking.
    I'm looking for a hash key that I can get in any moment and it is related to the user or the mobile.

    I looked into the Unity deviceUniqueIdentifier. But it can change its value. If it is happens the can't be decrypted again

    Have you ever had this issue?
    What kind of hash have you use?

    Thanks in advance
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    Data stored locally can not be easily protected from the owner of that local device.

    For example... whatever hash you resolve from the client is a hash found on the client's machine. This means, they know the hash!

    Furthermore, what's it to you if they access said data? It's there data... let them access it. Who cares if they hack their own gameplay. I used GameShark/ActionReplay/GameGenie growing up, ain't not problem with that!

    Unless you're referring to data that impacts other users. Such as in network/online play. In that case, keep that data on the server and not on the client. If you need to temporarily have data stored locally, encrypt that with keys generated on the server, and only give the client away to read the data (assymetrical encryption would be great in this situation).
     
  3. fulviodedalord

    fulviodedalord

    Joined:
    Apr 16, 2018
    Posts:
    2
    Hi lordofduct, Thanks for your answer.

    Our app has IAP, and we store locally what the user has bought. Our server is blind. Believe in client. Because the app can run offline and then sync with the server. We only use the server to validate the user and store the data.

    Thanks
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    As already mentioned, it is impossible to absolutely prevent 100% hacking of any local data. Storing data in a central server/database under your control is far better. If you just want to make it more difficult to mess around with local data, in my opinion anyone with the skill to figure out a static key you'd assign would also have the skill to figure out you're using a dynamic key based on some hardware identifier. So to avoid the issue of their hardware identifier changing, I'd just go with a hard coded static key. YMMV
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    OK... so I'm not going into full depth here as I'm not a paid consultant for you, nor am I a security expert. But I do have experience with it, so I'll just give you suggestions.

    1) Valid data is stored on the server. This is a MUST, don't fight this... you HAVE TO STORE IT ON YOUR SERVER. You're talking about monetary data, you can't just leave that laying around on any old device. That needs to be stored on your servers as secure as possible (I don't know the ins and outs of your IAP, but if there's an exploit that can make them profits like a return policy or an economy of some sort... it WILL be exploited... so put it on your damn server). Get over any buts right now, you CAN NOT store this validly on the users device. Just short of going the route of cryptocurrency level hashing, you're not going to secure that stuff (and even that relies on distributed security across multiple devices).

    ... Now, just because I said keep your data on the server doesn't mean you can't have offline play. I said keep your VALID data on the server. So, to get offline mode.

    2) Miscelaneous - Figure out if you just need offline play (no purchases), or offline purchasing as well.

    The former, with no offline purchases, is the easier of the two options (for very obvious reasons). If you want offline purchasing... well that gets into a giant bag of craziness (and legality I presume), that honestly I won't even touch with a 10 foot pole. Just don't do it is all.

    3) Keying/Encrypting - OK, so you're going to want to look into asymmetrical encryption. With this you have a public and private key. The private key is kept on the server and never released, the public key is given to the client device.

    When in online mode you'll be constantly validating all transactions in a normal server/client manner. When any validation/update to their data is performed a new version of their game state is encrypted on the server with the private key and sent to the client. They can use the public key to decrypt it and determine their own state (know how many 'coins' and 'items' they have).

    Thing is, since they don't have the private key, they can't modify this. So the next time they sync, they have the original version you gave them (which they need to validate with the server). And any new transactions are submitted as a separate 'diff' file that has recordings of every transaction they performed (any items/coins earned, any IAP, etc). Note, it's stored as a transaction log, and not as a new qty, so that each transaction can be re-performed on the the server for validation purposes. The new state then encrypted with the private key and sent back to the client.

    Note - this public/private key pair should be unique to each client (generating them is fairly trivial). And you should probably update them every few sessions.

    4) Transaction validation - (in this context when I say transaction, I mean changes to their stats... such as if you have a consumable in game, a transaction is the use of that consumable... or the winning of that consumable)

    When in offline mode each transaction hashes a 'token' for that transaction. This is done sequentially so that each new transaction hashes based on the token of the previous transaction combined with the options of this transaction (number of items sold, a transaction type id, etc etc) The starting token of course would be the last transaction token validated from the server (and probably stored in your encrypted 'state file'). This series of hashes is replicated on the server when it goes to validate. If any step in the transaction doesn't hash correctly, then it was a faulty transaction history and the client was up to no good (you could include timestamps to make sure they didn't do any clock fiddeling).

    But here's a problem... the client can just write a tool that generates a transaction history in the same manner. Guaranteeing that its transaction log appears valid.

    And this is where I don't have a fool proof answer to your problem.

    The best you can probably do is obfuscate the algorithm. For example you might tweak the algorithm from session to session. It's also best to have this validation not written in something as easily decompiled as C# or Java (again, still hackable, but much harder if it's compiled machine code rather than CIL).

    Other things to do is validate the transactions as plausible as well. Like if there's no way to get 100 coins in a 24 hour period, well then clearly that didn't happen (that being just a trivial example).

    ...

    But yeah, if anything, the tldr; takeaway from my post should be.

    DO NOT TRUST THE CLIENT