Page 1 of 1
Make unreadable save file
Posted: Mon Oct 28, 2013 11:36 am
by Joubarbe
Hi,
In the mini-game I'm currently developing, I generate a lot of random data when the user launches the application for the first time. I create lists, arrays, variables, etc. I would like to be able to retrieve these data and manipulate them to and from an external save file, and make it unreadable for the user. I'm a new user and I don't really know how to manage that in an efficient way. I could use the Packer and Cipher libraries, but I'm not sure if it's the best way to do that. Write a binary file ? Don't know either how to do that in PB (is there a writeBin kind of function ?).
I'm not going to have a "save file" button, but an active save system, where each action is stored at every moment and can never be "rollbacked". But I digress, it's another problem.
Thank you.
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 12:58 pm
by Shield
Simply said, it can't be done. Encryption can't work because it would require a password
that would also need to be stored on disk, rendering the encryption useless.
You can't prevent users from "cheating", it's their data, but you can make it a little more difficult.
In your case I'd go with a binary file and possibly scrambled data to make it less obvious.
Furthermore I'd include several checksums spread across the data. If the user modifies the save file,
he or she also needs to modify the checksums correctly which might not be that easy for "normal" users.
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 1:08 pm
by heartbone
Yes you can do that quite easily.
This program will demonstrate the concepts.
Instead of getting user input, and padding it to 16 characters,
simply build your 16 character KEY$ internal to your program and use it.
Something like KEY$=Chr$(39)+Chr$(101)+...
Code: Select all
KEYPAD$="123456789ABCDEF"
If OpenConsole()
ConsoleTitle("GRIDIRON'S File Crypter")
PrintN("Type in the filename to process.")
FILE$= Input()
If Len(FILE$) And FileSize(FILE$)>0
If OpenFile(1,FILE$)
PrintN("ENTER (up to) 16 CHARACTER KEY")
KEY$= Input()
LK= Len(KEY$)
If LK>0
If LK>16
KEY$= Mid(KEY$,1,16)
Else
If LK<16
KEY$= Mid(KEY$+KEYPAD$,1,16)
EndIf
EndIf
TOTSIZ= FileSize(FILE$)
*DECRY= AllocateMemory(TOTSIZ)
*ENCRY= AllocateMemory(TOTSIZ)
GETTYPE:
PrintN("Enter E for ENCRYPTION, D for DECRYPTION, OR Q TO QUIT")
TYPE$= Input()
If TYPE$="E" Or TYPE$="e"
ReadData(1,*DECRY,TOTSIZ)
CloseFile(1)
AESEncoder(*DECRY,*ENCRY,TOTSIZ,@KEY$,128,0,#PB_Cipher_ECB)
OpenFile(2,FILE$)
WriteData(2,*ENCRY,TOTSIZ)
CloseFile(2)
PrintN("FILE ENCRYPTED")
Delay(3000)
Else
If TYPE$="D" Or TYPE$="d"
ReadData(1,*ENCRY,TOTSIZ)
CloseFile(1)
AESDecoder(*ENCRY,*DECRY,TOTSIZ,@KEY$,128,0,#PB_Cipher_ECB)
OpenFile(2,FILE$)
WriteData(2,*DECRY,TOTSIZ)
CloseFile(2)
PrintN("FILE DECRYPTED")
Delay(3000)
Else
If TYPE$<>"Q" Or TYPE$<>"q"
Goto GETTYPE
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
CloseConsole()
EndIf
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 2:36 pm
by Joubarbe
Ok thank you heartbone I will try that.
@Shield : I'm a normal user in that case, and I have no idea how to do that

Encryption looks like a good idea, because the password is stored in a DataSection, not on an external file. Anyway, the goal is not to make a 100% cheat-proof software, I know it can't be achieved, and I don't like the idea of forbid access to your own files. But modifying some of them can be harmful for the application and can lead to CTDs, so I prefer to hide some of the main elements.
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 2:43 pm
by Shield
Well, storing the key in a data section is pretty much the same as in an external file.
I stick with my original recommendation.
If changing the files might cause harm in any way, checksums could help out there a lot.
Basically, if your program detects that a checksum is wrong it won't even attempt to "execute"
whatever it finds.
If you simply want to scramble you might as well use a faster algorithm,
for example simple and straight forward ROT13 (or similar procedures) to quickly scremble the data.
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 3:24 pm
by Joubarbe
Well, if someone has the "skill" to retrieve the password in the DataSection, he knows for sure that modifying a program is not harmless. That's not the case however if a user sees in a .txt file "NumberOfElement = 5" and decides to change it to 10,000 (leading the app to a crash).
But ! The checksim is maybe easier to implement than I thought, so I'll do some tests. (you're talking about the CRC32FileFingerprint() function ?)
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 3:38 pm
by Thorium
Thats a perfect example for XOR encryption. Makes the data unreadable by humans, is the fastest encryption, very easy to implement and understand even for someone who knows nothing about encryption and security is no priority.
Just search the forum there should be some codes.
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 4:03 pm
by luis
I agree with Thorium, a simple XOR would be more than enough to avoid human tampering.
If you want to do something extra you can add a checksum at the end/start of the file to verify it has not been touched. Since you have to XOR both when reading and writing, calculating and verifying a checksum come at practically no cost.
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 4:31 pm
by Joubarbe
What are the differences between heartbone's solution (AES encoding) — which I think it's fine — and XOR encoding ?
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 5:27 pm
by TI-994A
Joubarbe wrote:...make it unreadable for the user.
Joubarbe wrote:...if a user sees in a .txt file "NumberOfElement = 5" and decides to change it...
Hello Joubarbe. If the only requirement is to obfuscate the data from the casual user, a simple string scrambler should suffice. There are many ways to do it, but here's one example:
Code: Select all
Enumeration
#MainWindow
#String
#Scramble
#Unscramble
EndEnumeration
Procedure.s Scramble(normalString.s)
Protected scrambledString.s, zigZag = 1
normalString = ReverseString(normalString)
For L = 1 To Len(normalString)
scrambledString + Chr(Asc(Mid(normalString, L, 1)) + zigZag)
zigZag = -zigZag
Next L
ProcedureReturn scrambledString
EndProcedure
Procedure.s unScramble(scrambledString.s)
Protected normalString.s, zigZag = -1
For L = 1 To Len(scrambledString)
normalString + Chr(Asc(Mid(scrambledString, L, 1)) + zigZag)
zigZag = -zigZag
Next L
ProcedureReturn ReverseString(normalString)
EndProcedure
wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#MainWindow, 0, 0, 500, 100, "Text Obfuscation", wFlags)
ButtonGadget(#Scramble, 20, 30, 90, 30, "SCRAMBLE")
ButtonGadget(#Unscramble, 390, 30, 90, 30, "UNSCRAMBLE")
StringGadget(#String, 120, 30, 260, 30, "enter a test string here...")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
appQuit = 1
Case #PB_Event_Gadget
Select EventGadget()
Case #Scramble
SetGadgetText(#String, Scramble(Trim(GetGadgetText(#String))))
Case #Unscramble
SetGadgetText(#String, unScramble(Trim(GetGadgetText(#String))))
Case #String
Select EventType()
Case #PB_EventType_Focus
If Not init
SetGadgetText(#String, "")
init = 1
EndIf
EndSelect
EndSelect
EndSelect
Until appQuit = 1
Just a suggestion.

Re: Make unreadable save file
Posted: Mon Oct 28, 2013 5:37 pm
by Joubarbe
I can't achieve to open a BriefLZ archive. Is there a way to open that in an existing application like WinRAR ? Because if there isn't any, well, that's enough to keep users away

In any case, I think I'm going to use an archive, encode it, maybe add some checksum tests, and voila!
(and thanks - again - TI-994A for the suggestion)
Re: Make unreadable save file
Posted: Mon Oct 28, 2013 6:34 pm
by Shield
Thorium wrote:Thats a perfect example for XOR encryption.
Good idea, I agree!
@Joubarbe
I wasn't specifically talking about CRC32, but in general, yes.