Jump to content
    1. Welcome to GTAForums!

    1. GTANet.com

    1. GTA Online

      1. The Criminal Enterprises
      2. Updates
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Red Dead Online

      1. Blood Money
      2. Frontier Pursuits
      3. Find Lobbies & Outlaws
      4. Help & Support
    3. Crews

    1. Grand Theft Auto Series

      1. Bugs*
      2. St. Andrews Cathedral
    2. GTA VI

    3. GTA V

      1. Guides & Strategies
      2. Help & Support
    4. GTA IV

      1. The Lost and Damned
      2. The Ballad of Gay Tony
      3. Guides & Strategies
      4. Help & Support
    5. GTA San Andreas

      1. Classic GTA SA
      2. Guides & Strategies
      3. Help & Support
    6. GTA Vice City

      1. Classic GTA VC
      2. Guides & Strategies
      3. Help & Support
    7. GTA III

      1. Classic GTA III
      2. Guides & Strategies
      3. Help & Support
    8. Portable Games

      1. GTA Chinatown Wars
      2. GTA Vice City Stories
      3. GTA Liberty City Stories
    9. Top-Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    1. Red Dead Redemption 2

      1. PC
      2. Help & Support
    2. Red Dead Redemption

    1. GTA Mods

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Red Dead Mods

      1. Documentation
    3. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    4. Featured Mods

      1. Design Your Own Mission
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Rockstar Games

    2. Rockstar Collectors

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Movies & TV
      5. Music
      6. Sports
      7. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. Announcements

    2. Support

    3. Suggestions

*DO NOT* SHARE MEDIA OR LINKS TO LEAKED COPYRIGHTED MATERIAL. Discussion is allowed.

(C/C++) Using XOR for encryption


Saggy
 Share

Recommended Posts

I'm trying to figure out how to use XOR bitwise operation to create a simple encryption method that allows a user to input a key that is needed to encrypt and decrypt with.

 

 

#include <stdio.h>#include <stdlib.h>int main(int argc, char** argv){FILE *in=stdin,*out=stdout;if(argc>1)in=(argv[1][0]!='-')?fopen(argv[1],"rb"):stdin;if(argc>2)out=(argv[2][0]!='-')?fopen(argv[2],"wb"):stdout;char msg;while((msg = fgetc(in)) != EOF) { msg = msg ^ argv[3][0] ^ argv[3][1] ^ argv[3][2] ^ argv[3][3] ^ argv[3][4] ^ argv[3][5] ^ argv[3][6] ^ argv[3][7] ^ argv[3][8] ^ argv[3][9] ^ argv[3][10] ^ argv[3][11] ^ argv[3][12] ^ argv[3][13] ^ argv[3][14] ^ argv[3][15] ^ argv[3][16] ^ argv[3][17] ^ argv[3][18] ^ argv[3][19] ^ argv[3][20] ^ argv[3][21] ^ argv[3][22] ^ argv[3][23] ^ argv[3][24] ^ argv[3][25] ^ argv[3][26] ^ argv[3][27] ^ argv[3][28] ^ argv[3][29] ^ argv [3][30] ^ argv[3][31] ^ argv[3][32]; fprintf(out, "%c", msg);}     fclose(in);fclose(out);return 0;}

 

 

Usage

programname filein[-] fileout[-] key

Use '-' for stdin or stdout

 

What I'm trying to do here is use each character in the supplied key within the bitwise operation, so that if any of them were different, it wouldn't decode correctly. While it sounds somewhat good in theory, and in practice it was even more misleading with many results that made it seem spot on, I've found out that it just doesn't operate in the way I want it to.

 

If I use "passwordpassword" as a key, just for kicks, I can then decode it perfectly fine with "mdsswordmdssword". While there are not many more instances where it will decode perfectly, if I change each digit to either plus or minus one space on the ASCII chart, then more and more parts of the text will begin to show themselves.

 

I don't have much of an understanding of why this is happening, but I have a good hunch it's because of the way the XOR operator is changing the bits around. Apparently "md" is the same as "pa" in bits after XOR, and I'm wondering just how many instances of this there are.

 

 

Is there a better direction I could be going to do this? Someone suggested that I try using XOR to do it because they knew of a good few programs that used user-supplied keys and XOR, but I just can't seem to come to a good enough understanding of how it works in order to even begin to understand why I'm having this issue. Of the few programs I've found that use the XOR and user-supplied key combination, they use MD5 somehow in the operation, but I haven't found any details on how. Here is a good example:

http://www.myersdaily.org/joseph/javascript/alphac.html

 

As a side note, I'm getting more into the area of cryptography and it seems to be a good area to practice C with. It seems to be hard to find vary many cryptography program examples though, anyone know of any specialty programming sites heard around cryptography? I know there's google, but I just wonder if anyone knows personally of any really good ones. It doesn't exactly seem to be a popular subject.

 

Edit

 

As a side note, I think I discovered another problem. Using it like this, the order of the characters does not matter. So if you use a keyword like "sucks" you can then decode with "sckus" without any problem. I've tested this on some pretty long strings, and it seems to hold true on strings of any lenth. For example, "rbf)R{sXviUO$MIvrisOdXgc<hQV7koL" will be decoded by "rbf)R{sXviUO$<IvrisOdXgcMhQV7koL" even with the 'M' and '<" switched.

 

I think the reason for this is because with XOR the position of the character must have no effect on the resulting bit value, but I'm not sure if that's what it is or how to rectify that.

Edited by SagaciousKJB

QUOTE (K^2) ...not only is it legal for you to go around with a concealed penis, it requires absolutely no registration!

Link to comment
Share on other sites

Use a different character of the key with different characters of the message. Also, I'd use feof(FILE*) function to check for file end. Otherwise, you might get early termination because of the \0 character in file.

 

Here is how I would do it.

 

#include <stdio.h>#include <strings.h>int main(int argc, char **argv){FILE *in=stdin,*out=stdout;char msg;int l,i;if(argc>1)in=(argv[1][0]!='-')?fopen(argv[1],"rb"):stdin;if(argc>2)in=(argv[2][0]!='-')?fopen(argv[2],"wb"):stdout;if(argc<4){ printf("No key suplied.\n"); return 0;}i=0;l=strlen(argv[3]); //Length of the key.while(!feof(in)){ msg=fgetc(in); msg^=argv[3][i]; fprintf(out,"%c",msg); i++; if(i>=l)i=0;}fclose(in);fclose(out);return 0;}

 

 

Edit: The XOR operator gives 1 if input bits are 1,0 or 0,1. If both are 0 or both are 1, it gives you 0. Because of that, anything^anything = 0, and something ^ 0 = something. So ((msg^key)^key) = msg^(key^key) = msg ^ 0 = msg. That means that if you run the same key twice, you get original file back.

 

There is a slight problem with this encryption. It's really easy to break if you know something about the file you want to crack. So don't use it on files you want to hide from FBI. Other than that, it's pretty nifty.

 

Hope that helps.

Edited by K^2

Prior to filing a bug against any of my code, please consider this response to common concerns.

Link to comment
Share on other sites

 

Use a different character of the key with different characters of the message. Also, I'd use feof(FILE*) function to check for file end. Otherwise, you might get early termination because of the \0 character in file.

 

Here is how I would do it.

 

#include <stdio.h>#include <strings.h>int main(int argc, char **argv){FILE *in=stdin,*out=stdout;char msg;int l,i;if(argc>1)in=(argv[1][0]!='-')?fopen(argv[1],"rb"):stdin;if(argc>2)in=(argv[2][0]!='-')?fopen(argv[2],"wb"):stdout;if(argc<4){ printf("No key suplied.\n"); return 0;}i=0;l=strlen(argv[3]); //Length of the key.while(!feof(in)){ msg=fgetc(in); msg^=argv[3][i]; fprintf(out,"%c",msg); i++; if(i>=l)i=0;}fclose(in);fclose(out);return 0;}

 

 

Edit: The XOR operator gives 1 if input bits are 1,0 or 0,1. If both are 0 or both are 1, it gives you 0. Because of that, anything^anything = 0, and something ^ 0 = something. So ((msg^key)^key) = msg^(key^key) = msg ^ 0 = msg. That means that if you run the same key twice, you get original file back.

 

There is a slight problem with this encryption. It's really easy to break if you know something about the file you want to crack. So don't use it on files you want to hide from FBI. Other than that, it's pretty nifty.

 

Hope that helps.

Yeah, I've been reading up on it, you can XOR the plaintext bits with the ciphertext bits and the result will be the key bits you used to encrypt with, but like you said it's pretty nifty, and I was just trying my hand at writing a program for it.

 

I had a few more days to work on my code, and wound up with this

 

 

#include <stdio.h>#include <stdlib.h>#include <string.h>int main(int argc, char** argv){FILE *in=stdin,*out=stdout;/*File handling scheme, if the first letters are - use stdin or stdout, if not use the stringe as filename*/if(argc>1)in=(argv[1][0]!='-')?fopen(argv[1],"rb"):stdin;if(argc>2)out=(argv[2][0]!='-')?fopen(argv[2],"wb"):stdout;int msg;unsigned int strl = strlen(argv[3]);unsigned int i = 0;while((msg = fgetc(in)) != EOF) { msg = msg ^ argv[3][i]; fprintf(out, "%c", msg); if(i < strl) { 	i++; } else if(i == strl) { 	i = 0; }}     fclose(in);fclose(out);return 0;}

 

 

It looks pretty similar to yours, aside from the usage of feof(). I have noticed a couple of occurrences of the text being cut short, so I think I will use feof(). The only thing is that with the loop like

 

 

while(!feof(in)) {               msg = fgetc(in);               msg = msg ^ argv[3][i];               fprintf(out, "%c", msg);               if(i < strl) {                       i++;               }               else if(i == strl) {                       i = 0;               }       }

 

 

It spits out an extra character at the end ( on a new line usually ), so I haven't been able to figure out where that's coming from yet, but even though using EOF has only cut it short once or twice, I'd still rather use feof. Guess I've got more tracking down to do.

QUOTE (K^2) ...not only is it legal for you to go around with a concealed penis, it requires absolutely no registration!

Link to comment
Share on other sites

Hmm... It might not throw feof until it tries reading past the end of file. If that really is the cause, try make the following change.

 

if(!feof(in))fprintf(out, "%c", msg);

 

Just check to make sure this doesn't cut off the last byte of your cypher.

Prior to filing a bug against any of my code, please consider this response to common concerns.

Link to comment
Share on other sites

Well, that seems to work perfectly, every bit and byte seems to be where it should be, that is it deciphers and enciphers correctly without loss of any characters. Thanks for the help on that, it seems to be working perfectly now.

 

The only thing I might want to do is figure out a way to fill in the rest of the key with a random sequence to match the length of the message, that way the key won't be repeated all throughout the message and will be less susceptible to frequency analysis.

 

I was thinking about learning another algorithm like RC4 that uses XOR in its operations, but all of the practical C examples I can find don't actually use "^", but "%". Like this excerpt example:

 

 

// Key Scheduling Algorithm// Input: state - the state used to generate the keystream//        key - Key to use to initialize the state//        len - length of key in bytes  void ksa(unsigned char state[], unsigned char key[], int len){ int i,j=0,t; for (i=0; i < 256; ++i)    state[i] = i; for (i=0; i < 256; ++i) {    j = (j + state[i] + key[i % len]) % 256;    t = state[i];    state[i] = state[j];    state[j] = t; }  }

 

 

http://bradconte.com/code/rc4_c

 

I haven't actually tested it out, just referencing it as some of the only C code I can find that demonstrates various algorithims. The person that coded it also coded AES, DES, 3DES, and some hashing algorithims too, but right now I can't really even figure out how the simple RC4 one works.

 

 

Even though the practicality of it all is useless ( text encryption, wooo), it's still nifty to fool around with this stuff. One of the reasons I started learning about XOR was to try to use it in my own algorithm because from what I've heard most algorithims use it. I've learned from various sources how easy it is to crack simple XOR encryption, so I doubt I'll be able to think of a way to use it in strong encryption until I understand how its used in those other algorithims.

 

Edit

 

About that completely useless remark, I hadn't realized until just now that I could actually use this program to encrypt or decrypt data. I never stopped to think that my own custom program didn't encrypt or decrypt data because it didn't handle all data, but this does. I wonder if it's a good or bad sign that I just wrote a program that can encrypt data by accident.

 

There is a problem though, the program will segment fault on Linux when trying to encrypt a file larger than around 2.5 GB ( from what I've tested so far). I'm not sure if this is a result of the Linux kernel itself.

 

This is the strace result

 

execve("/usr/bin/xor", ["xor", "./gtasa.iso", "-", "doesnotmattertest"], [/* 37 vars */]) = 0brk(0)                                  = 0x804a000access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f34000access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)open("/etc/ld.so.cache", O_RDONLY)      = 3fstat64(3, {st_mode=S_IFREG|0644, st_size=61789, ...}) = 0mmap2(NULL, 61789, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7f24000close(3)                                = 0access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)open("/lib/tls/i686/cmov/libc.so.6", O_RDONLY) = 3read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\260a\1"..., 512) = 512fstat64(3, {st_mode=S_IFREG|0644, st_size=1339816, ...}) = 0mmap2(NULL, 1349136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7dda000mmap2(0xb7f1e000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x143) = 0xb7f1e000mmap2(0xb7f21000, 9744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7f21000close(3)                                = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7dd9000set_thread_area({entry_number:-1 -> 6, base_addr:0xb7dd96b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0mprotect(0xb7f1e000, 4096, PROT_READ)   = 0munmap(0xb7f24000, 61789)               = 0brk(0)                                  = 0x804a000brk(0x806b000)                          = 0x806b000open("./gtasa.iso", O_RDONLY)           = -1 EFBIG (File too large)--- SIGSEGV (Segmentation fault) @ 0 (0) ---+++ killed by SIGSEGV (core dumped) +++Process 3066 detached

 

 

This part and the fact that I can encode and decode files that large on Windows makes me think it's some limitation with Linux, but I wouldn't know what or how to rectify it. I don't really ever forsee encrypting anything with this, let alone a file over 2 gigs, but it would be nice to know what the limitation here is. Obviously, "open("./gtasa.iso", O_RDONLY) = -1 EFBIG (File too large)" is what clues me in on the file being to large, but what is the limit, is there a way to change it, etc.

Edited by SagaciousKJB

QUOTE (K^2) ...not only is it legal for you to go around with a concealed penis, it requires absolutely no registration!

Link to comment
Share on other sites

Are you reading it from a network mount? I know that smbfs has a 2gb file size limit, the newer alternative cifs does a better job.

 

If it's on a local filesystem such as EXT3 or ReiserFS then it's odd, they should be able to handle large files just fine.

Link to comment
Share on other sites

Are you reading it from a network mount? I know that smbfs has a 2gb file size limit, the newer alternative cifs does a better job.

 

If it's on a local filesystem such as EXT3 or ReiserFS then it's odd, they should be able to handle large files just fine.

It's a problem in the C library. He already found a fix.

Prior to filing a bug against any of my code, please consider this response to common concerns.

Link to comment
Share on other sites

Yeah, here's the link explaining the fix, in case anyone else wants to reference it.

 

Edit

 

Wow, I guess that did no one any good after a few months of not being there... Whoops.

 

Here's the link:

http://mail.nl.linux.org/kernelnewbies/2001-12/msg00186.html

Edited by SagaciousKJB

QUOTE (K^2) ...not only is it legal for you to go around with a concealed penis, it requires absolutely no registration!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.