Skip to main content
gamedev.net
🔒 Locked

Encryption

Started by jt_845s 21 replies 1.3k views
Original Post
jt_845s
jt_845s
I want all of my maps and other misc. data in my game to not be easily accessable by the end user. I decided to encrypt the files and unencrypt them when accessing the data. My functions look like this: #include #include #include #define ENCRYPT_LEVEL 16 void encrypt(char* string) { for (int i=0; i = string[i] + ENCRYPT_LEVEL; } void unencrypt(char* string) { for (int i=0; i
[source]#define ignite_software 1[/source]
furby100
furby100
XOR encryption is a better encryption than simply adding a number and then subtracting it. Take a 32 bit number or so, and then XOR everything by it. To decrypt, you just XOR is by the same number. Works every time.

PS. Whenever you put an i between two brackets the forum software interprets that as italics. For example, if I put this is all in italics . However, if I put [ i ]This is not in italics[ /i ]. Just thought you might want to use index instead of i.

------------------------------
#pragma twice


sharewaregames.20m.com

Edited by - furby100 on October 12, 2000 12:37:58 PM

Buster
Buster
That sounds interesting... where would I get a look at zlib?
jt_845s
jt_845s
ok, how do i use XOR? an example would help. thanx.

#define ignite_software 1
[source]#define ignite_software 1[/source]
NuffSaid
NuffSaid
Here are your functions changed to use XOR instead of +/-

    
void encrypt(char* string)
{
for (int i=0; i string = string<i> ^ ENCRYPT_LEVEL;
}

void unencrypt(char* string)
{
for (int i=0; i string[i] = string[i] ^ ENCRYPT_LEVEL;
}



NOTE:- The XOR operator is ^.

Hope that helps
==========================================In a team, you either lead, follow or GET OUT OF THE WAY.
jt_845s
jt_845s
yeah, thanx.

#define ignite_software 1
[source]#define ignite_software 1[/source]
fugue88
fugue88
Even just XOR''ing your entire data set isn''t very secure if you''re using only a single value. Try doing some operation on your encryption key after every operation, to keep it changing. For example, say ENCRYPT_LEVEL is an int instead of a #define, then you could insert ENCRYPT_LEVEL *= 119; or such at the bottom of your loop.
KalvinB
KalvinB
I got one of those CueCats from Radio Shack because it''s free and I wrote a program to decode the output. My program''s in VB and does exactly what your trying to do kinda.

ConvBinary is the XORed byte that is used on every character in the string. If you wanted you could have as many bytes as you wanted.

NumDots is just a variable to check to see if it''s a valid input from the CueCat which uses periods to seperate fields.

TempBinary is the CueCat''s text converted to 6bits per character (Base 64) and mushed together and then XORed by the 8bit key.

Base64$() is the 64 character array that is used by the CueCat.

Hope this helps. For my game I just convert everything to base 256 and compress. How everything is stored is also somewhat random. If the file gets one byte off it won''t load correctly. I just cram everything together with no seperator and in binary format.

Ben

    
Private Sub Command1_Click()
If Text1.Text = "" Then GoTo BadMonkey
Text3.Text = "
"
Text4.Text = "
"
Text5.Text = "
"
Text6.Text = "
"
Text7.Text = "
"
Text8.Text = "
"
Text9.Text = "
"

NumDots = 0

For j = 1 To 256
If Mid$(Text1.Text, j, 1) = "
." Then NumDots = NumDots + 1
Next
If NumDots <> 4 Then GoTo BadMonkey

Dim TempBinary(1024)
Dim ConvBinary(8)

ConvBinary(1) = 0
ConvBinary(2) = 1
ConvBinary(3) = 0
ConvBinary(4) = 0
ConvBinary(5) = 0
ConvBinary(6) = 0
ConvBinary(7) = 1
ConvBinary(8) = 1


j = 1
t = 0
NumDot = 0
OldT = 1
While NumDot < 4

If Mid$(Text1.Text, j, 1) = "
." Then
NumDot = NumDot + 1

If NumDot > 1 Then
For q = OldT To t Step 8
temp = 0
For k = 0 To 7
temp = temp + 2 ^ (7 - k) * TempBinary(q + k - 1)
Next
If NumDot = 2 Then Text6.Text = Text6.Text + Chr(temp)
If NumDot = 3 Then Text8.Text = Text8.Text + Chr(temp)
If NumDot = 4 Then Text9.Text = Text9.Text + Chr(temp)
Next

OldT = t + 1
End If
Else

For b = 1 To 64
If Mid$(Text1.Text, j, 1) = Base64$(b) Then
temp = b - 1
StartComp = 32

For k = 1 To 6
If temp >= StartComp Then
temp = temp - StartComp
TempBinary(t) = 1
Else
TempBinary(t) = 0
End If
StartComp = StartComp / 2

Text3.Text = Text3.Text & TempBinary(t)
Text4.Text = Text4.Text & ConvBinary(t Mod 8 + 1)
If TempBinary(t) <> ConvBinary(t Mod 8 + 1) Then TempBinary(t) = 1 Else TempBinary(t) = 0
Text5.Text = Text5.Text & Chr$(TempBinary(t) + 48)
t = t + 1
Next
End If
Next
End If

j = j + 1
Wend



GoTo DoneMonkey

BadMonkey:
Text1.Text = "
Scan A BarCode stupid!"

DoneMonkey:
Text7.Text = Text1.Text
Text1.Text = "
"
Text1.SetFocus
End Sub



LilBudyWizer
LilBudyWizer
You don''t want to get too caught up in trying to defeat hackers. Everything you can do they can undo. You make it impossible for them to figure out how the file is encoded so they disassemble your program. All you want to do is discourage the casual hacker. The more you put into stopping a hacker the less time you have to make a good game. The fundamental truth is that as long as your program runs on their computer you have no control over it. No matter how difficult it is to hack a program someone will do it and when they do they will give their hard gained knowledge to anyone that wants it. Diablo I on battle.net wasn''t destroyed by thousands of highly skilled hackers. It was destroyed by thousands of people that knew little more than how to run a program.
Keys to success: Ability, ambition and opportunity.
capn_midnight
capn_midnight
XOR encryption looks too easy. If it''s easy to do, it''s easy to break.
Using a one-time pad cypher, you can be sure that your stuff will be completely secure, but it would not work for your scale, or the repetitive nature of your data. Forget what I said about one-time pad cyphers.
You could use a nearly unbreakable cypher, though. Check out this grid:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
BCDEFGHIJKLMNOPQRSTUVWXYZA
CDEFGHIJKLMNOPQRSTUVWXYZAB
DEFGHIJKLMNOPQRSTUVWXYZABC
EFGHIJKLMNOPQRSTUVWXYZABCD
FGHIJKLMNOPQRSTUVWXYZABCDE
GHIJKLMNOPQRSTUVWXYZABCDEF
HIJKLMNOPQRSTUVWXYZABCDEFG
IJKLMNOPQRSTUVWXYZABCDEFGH
JKLMNOPQRSTUVWXYZABCDEFGHI
KLMNOPQRSTUVWXYZABCDEFGHIJ
LMNOPQRSTUVWXYZABCDEFGHIJK
MNOPQRSTUVWXYZABCDEFGHIJKL
NOPQRSTUVWXYZABCDEFGHIJKLM
OPQRSTUVWXYZABCDEFGHIJKLMN
PQRSTUVWXYZABCDEFGHIJKLMNO
QRSTUVWXYZABCDEFGHIJKLMNOP
RSTUVWXYZABCDEFGHIJKLMNOPQ
STUVWXYZABCDEFGHIJKLMNOPQR
TUVWXYZABCDEFGHIJKLMNOPQRS
UVWXYZABCDEFGHIJKLMNOPQRST
VWXYZABCDEFGHIJKLMNOPQRSTU
WXYZABCDEFGHIJKLMNOPQRSTUV
XYZABCDEFGHIJKLMNOPQRSTUVW
YZABCDEFGHIJKLMNOPQRSTUVWX
ZABCDEFGHIJKLMNOPQRSTUVWXY


now, you have to come up with a key, the longer the better, the less repetitive the better. If you use the top row and the left-most collum like number lines and use the letters like a coordinate system, then using the first character in you key and the first character in you data, you can track across to the point where they cross and get the encrypted letter. Check out this example:
DATA: hello how are you
KEY: iamgoodhowareyou
the first letter in the data is ''h'', the first letter in the key is ''i''. Track h across the top and i down the side, where the two cross is the new letter, P. I''ll skip ahead and do the rest
PEXRC KVK AGI MIC
Since the last letter in the data did not have a key letter associated with it I started back at the beginning of the key.
Notice certain things about the encrypted data. The two ''l''s in hello are encrypted differently (X and R) while the ''h'' and ''w'' in how are encrypted the same (K) this makes an almost completely random code. Now, if you use a random string for the key, and apply it to non-readable data (machine-code, map data, whatever), then you will get something that is virtually unbreakable. The thing about this code is that depending on what the key is, it could mean something completely different, especially if the key is random.
There is only one way to break the code. You hope that the key is not random, and you hope that the encrypted data is a rather long passage of text. then, you guess that certain words are the word ''the'', then you work out a partial key. If you come up with a key that makes sense (a word perhaps) then you know your on the right track. You continue in this manner until you get the entire key, or enough of it that you can guess the rest. But this is only if the key was a phrase and the data was readable text.
You can add any character you want to this, then reference it easily, especially with a C/C++ program:
    
#include <stdio.h>
char codepad[256][256];

void make_codepad(void)
{
int x, y;
char c;
for(y=0;y<256;y++){ //256 character set

for(x=0;x<256;x++){
c=(y*256)+x;
while(c>=256) c-=256;
codepad[y][x]=c;
}
}
}

char encrypt(char data, char key)
{
char code;
code=codepad[key][data];
return code;
}

char decrypt(char code, char key)
{
char data;
int y;
for(y=0;y<256;y++){
if(code==codepad[y][key]) data=y;
}
return data;
}

void main()
{
char data[6]="Hello";
char data2[6];
char key[6]="Howdy";
char code[6];
int n;
for(n=0;n<6;n++){
code[n]=encrypt(data[n],key[n]);
printf("%c",code[n]);
}
putchar(10);
for(n=0;n<6;n++){
data2[n]=decrypt(code[n],key[n]);
printf("%c",data2[n]);
}
putchar(10);
}

and that should be it!
MadKeithV
MadKeithV
One of the basic rules of safe encryption:
Always assume that the person trying to hack your data knows the algorithm you used to encrypt it.
Note that this does NOT mean that the hacker will be able to see your data - he/she will not have the key, and the difficulty should be in figuring out what the key is.


People might not remember what you said, or what you did, but they will always remember how you made them feel.
~ (V)^|) |<é!t|-| ~
It's only funny 'till someone gets hurt.And then it's just hilarious.Unless it's you.
CobraA1
CobraA1
Finding the key isn't that hard. After all, the program itself has to have access to the key in order to run. Therefore, the hacker runs the program, and tries to find the key while the program is running. He/she finds all of the locations that the decryption algorithm accesses while running. One of those locations has to be the key. That easily defeats capn_midnight's code. There are tools for scanning memory locations while a program is running.

I agree with Wizer. Keep the casual hacker out, but don't expect to defeat every hacker in the world. It's next to impossible.

Many times, the hacker simply uses your own decryption algorithm to access the files -- make sure the key isn't in the decryption algorithm itself.

capn_midnight also made another no-no: He hard-coded the password into the code in plain sight; that's the first place somebody will look. The password should itself be encoded/encrypted.

Here's a good article on the subject: http://www.gamasutra.com/features/20000724/pritchard_01.htm


Edited by - CobraA1 on October 13, 2000 2:25:51 PM
"If a man does not keep pace with his companions, perhaps it is because he hears a different drummer. Let him step to the music he hears, however measured or far away"--Henry David Thoreau
Chris Hargrove
Chris Hargrove
Cobra and Wizer are correct; it is virtually impossible to prevent the breaking of your encryption algorithm. All you can do is make it difficult for the hackers/crackers, but you can''t stop them completely.

While simple encryption and such will stop the casual hacker, it will not discourage the skilled ones. This usually isn''t a problem, unless the skilled ones pass their results (in the form of cracks, cheat programs, etc.) on to the masses, which often happens. If your algorithm and key are available somewhere in your program, they will be able to find it if they work hard enough.

Of course, you can make that a *lot* of work for them. Many people who do this kind of thing rely on tools such as SoftICE and other debuggers/disassemblers. If you''re absolutely diehard about giving these folks a hard time, there are tricks you can pull that can A) make your program virtually impossible to disassemble correctly, B) detect a good number of debuggers and disassemblers, C) *crash* several of these debuggers (such as SoftICE) when detected, D) prevent many of them from working by doing things like attaching your code into kernel32''s address space (where many debuggers will refuse to go), and so forth.

All of these things can be done, and while they will not stop people who insist on deciphering your techniques forever, it can at least delay and annoy them. But many of these tricks are a lot of work, and you must ask yourself how far you really want (or need) to go.
BitBlt
BitBlt
Here''s another idea. I think you have to hit Ctrl-D to fire up SoftIce while another prog is running. It may be possible to "filter" the keyboard and if they hit this key combination then just disregard it and through it out in the trash.



"We are the music makers, and the dreamers of the dreams."
- Willy Wonka
Chris Hargrove
Chris Hargrove
I believe SoftICE traps the keyboard at a lower level than the application (possibly through a VxD or whatnot), so you may not be able to filter it. However, you can detect and remove SoftICE''s presence via other means (although they''re not trivial to implement).
BitBlt
BitBlt
Too bad, I guess you can''t even override it with asm then.



"We are the music makers, and the dreamers of the dreams."
- Willy Wonka
nickm
nickm
Well, if SoftICE traps the keyboard by using Vxd stuff, why couldn''t you game do the same thing, so you get control over the keyboard and filter out keys used by SoftICE?
compumatrix
compumatrix
"If someone can make it, someone else can unmake it" - quote (or some variation thereof) from "The Score."

Anyway the point is that it is impossible to make an unbreakable encryption algorithm or key. It may take someone a really unreasonable amount time to break it (as is the case with encryption used for protecting e-commerce) but it can still be done.

In the context of games and not allowing people to tamper with the files, you should just make it hard for the casual hacker to tamper with them.
Null and Void
Null and Void
You should ask yourself: Why shouldn''t anyone be able to access the files? There are a couple reasons where I could see you not allowing them to tamper with the files, but in most cases you aren''t helping yourself or the user, just being annoying.

BTW: Checksums are probably a better idea than encryption.

[Resist Windows XP''s Invasive Production Activation Technology!]
Blueshift
Blueshift
For encryption: If you want good security, then you should use a ''real'' encryption system, such as RC-5 or Blowfish.

Look at: http://cnscenter.future.co.kr/crypto/algorithm/block.html

For debugging: Hard to stop a debugger. Professional reverse engineer experts use hardware debuggers, these are systems that are directly connected to the CPU / Chipset, there is no way of stopping those.

Don''t try to defeat the debugger, try to defeat the hacker''s brain

A very good way is to create a decryption system based on a stack based virtual machine. Self modifying opcodes, procedural branching systems, self decrypting boolean tables and code.
Several years ago, I took part in a hacking contest, the objective was to hack a tiny little DOS programm called ''hackme.com''. It''s size was exactly 4353 bytes. It was written by some russian guy, and used all the techniques described above. It was virtually impossible to hack, at least 200 people tried it. In the end, some totally sick guy, who debugged it for over 48 hours nonstop (!), managed to break it.

Keep in mind that the more you will secure your data, the more people will be tempted to hack it (''What is he hiding with *such* an encryption system ??'').

Null And Void: I don''t think that checksum is a good idea. I think the point is not to prevent tampering, but to prevent ripping of eg. textures. So encryption will be the better choice.

A.H aka Blueshift

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.