XOR cipher help - fstream binary wrting

XOR cipher help - fstream binary wrting

Post by fabianhjr on Mon Nov 01, 2010 8:49 pm
([msg=48442]see XOR cipher help - fstream binary wrting[/msg])

Code: Select all
/*--------------------------------------------------------------------------------
===== Copyright =====
Copyright (c) 2010 Fabian Heredia

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgment in the product documentation would be
   appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
   distribution.

===== Explanation =====
    The XOR cipher is based uppon boolean logic XOR. The cipher uses the 2
strings[plain & key] to safely encrypt the first(bit by bit).
Table:
---------------
| A | B | XOR |
| 0 | 0 |  0  |
| 0 | 1 |  1  |
| 1 | 0 |  1  |
| 1 | 1 |  0  |
---------------
    If you have acces to at least two of the three [plain, key, ciphered]
the remaining one is no longer protected. It is recommended to use a key
at most once since an attacker could start seeing patterns.
--------------------------------------------------------------------------------*/
#include <iostream>
#include <fstream>
#include <string>
#include <limits.h>
using namespace std;

// Cipher explained avobe.
string cipher(string toCrypt, string key){
    string crypted = toCrypt;
    unsigned int iK = key.length(), iC = toCrypt.length();
    for(unsigned int i = 0, j = 0; i < iC; i++){
        crypted[i] = toCrypt[i] ^ key[j]; // ^ is the operator for Bitwise XOR
        if(j++ == iK){j = 0;}
    }
    return crypted;
}

// Function for writing into a file.
int write(string toWrite, string file)
{
    ofstream output(file.c_str(), ios::binary);
    if(output.is_open())
    {
        output << toWrite;
        output.close();
    }
    else { return 1;}
    return 0;
}

int main(int argc, char *argv[]){
    // If we recieve exactly 3 arguments.[Plain, Key, ,and Output file]
    if(argc == 4)
    {
        if(write(cipher(argv[1], argv[2]), argv[3]))
        {
            cout << "FAILED";
        }
    }
    // If we recieve exactly 2 arguments.[File and Key]
    else if(argc == 3)
    {
        // TODO: File Manipulation
    }
    else if(argc > 1)
    {
        cout << argv[0] << endl;
        cout << "Usage:" << endl;
        cout << "\t1) 0 arguments - Utility for ciphering a file/text." << endl;
        cout << "\t2) 2 Arguments - [File to cipher] and [key]" << endl;
        cout << "\t3) 3 Arguments - [Plain], [key], and [output file]." << endl;
    }
    // If we recieve no arguments
    else
    {
        string plain, key, output;
        cout << "File: ";
        cin >> output;
        cin.ignore(INT_MAX, '\n');
        ifstream file(output.c_str(), ios::binary);
        if(file.is_open())
        {
            cout << "Key: ";
            cin >> key;
            cin.ignore(INT_MAX, '\n');

            // Loading file contents to memory.
            unsigned int size = file.tellg();
            char * mem = new char [size];
            file.seekg (0, ios::beg);
            file.read(mem, size);
            file.close();
            // Writing and cleaning up.
            write(cipher(mem, key), output.c_str());
            delete[] mem;
        }
        else
        {
            cout << "Plain: ";
            cin >> plain;
            cin.ignore(INT_MAX, '\n');
            cout << "Key: ";
            cin >> key;
            if(write(cipher(plain, key), output))
            {
                cout << "FAILED!";
            }
        }
    }
    return 0;
}

cipher() works great. However, when I write into a file it start losing data and it doesn't come back as the plaintext. Any idea what I am doing wrong?
Donate bitcoins to me! [1DhRP3hHgmSLQdRTZyT8VPTmzAj7Z2rsGA]
Dunno what bitcoins are? BitcoinMe
fabianhjr
Poster
Poster
 
Posts: 286
Joined: Tue Sep 21, 2010 7:48 pm
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by tucak on Tue Nov 02, 2010 6:56 am
([msg=48460]see Re: XOR cipher help - fstream binary wrting[/msg])

When you are reading the file in, you forgot to jump to the end, before getting the position.
Code: Select all
            if(file.is_open())
            {
                cout << "Key: ";
                cin >> key;
                cin.ignore(INT_MAX, '\n');

                // Loading file contents to memory.
                file.seekg(0,ios::end); // Jump to the end!
                unsigned int size = file.tellg(); // get the last position
                char * mem = new char [size];
                file.seekg (0, ios::beg);
                file.read(mem, size);
                file.close();
                // Writing and cleaning up.
                write(cipher(mem, key), output.c_str());
                delete[] mem;
            }
tucak
New User
New User
 
Posts: 47
Joined: Wed Jun 04, 2008 12:20 pm
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by tgoe on Tue Nov 02, 2010 7:48 am
([msg=48462]see Re: XOR cipher help - fstream binary wrting[/msg])

You're essentially working with raw bytes. You shouldn't be using string at all.

And cipher() has an off-by-one error:
Code: Select all
    for(unsigned int i = 0, j = 0; i < iC; i++){
        crypted[i] = toCrypt[i] ^ key[j]; // ^ is the operator for Bitwise XOR
        if(j++ == iK){j = 0;} // j isn't incremented until *after* the boundary check
    }
User avatar
tgoe
Contributor
Contributor
 
Posts: 668
Joined: Sun Sep 28, 2008 2:33 pm
Location: q3dm7
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by thetan on Tue Nov 02, 2010 8:03 pm
([msg=48485]see Re: XOR cipher help - fstream binary wrting[/msg])

O_O holy fucking sheep shit bat man. Who the fuck taught you to get the size of a file like that?!? Whoever it was, they should be fucking shot on site for fail.

use stat() to get the file size before you open it.

Also, i absolutely despise random access on files. I must recommend mmap() as an alternative. I'm at work atm so i can't post a super detailed post on anything, but code speaks louder then words imo. check this out i whooped to together typing at the speed of light in emacs.
Code: Select all
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int get_file_size(char *file)
{
  struct stat statb;
  return (!stat(file, &statb)) ? (int) statb.st_size : -1;
}

int main(int argc, char *argv[])
{
  char *contents;
  int fd, size;

  if ((size = get_file_size("./rawr")) == -1)
  {
    fprintf(stderr, "No such file diqhed!\n");
    return 1;
  }

  if (!(fd = open("./rawr", O_RDONLY)))
  {
    fprintf(stderr, "wooops, cant open that file.\n");
    return 1;
  }

  contents = mmap((caddr_t)0, size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (contents == (char*) -1)
  {
    fprintf(stderr, "god damnit, mmap b0rked on us\n");
    return 1;
  }

  write(0, contents, size);
 
  return 0;

}
"If art interprets our dreams, the computer executes them in the guise of programs!" - SICP

Image

“If at first, the idea is not absurd, then there is no hope for it” - Albert Einstein
User avatar
thetan
Contributor
Contributor
 
Posts: 657
Joined: Thu Dec 17, 2009 6:58 pm
Location: Various Bay Area Cities, California
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by fabianhjr on Thu Nov 04, 2010 7:36 pm
([msg=48562]see Re: XOR cipher help - fstream binary wrting[/msg])

At least I got some more free time.

No one teaches me. I am doing a try & error approach. I scrapped everything and attempt it again.
Code: Select all
/*--------------------------------------------------------------------------------
===== Copyright =====
Copyright (c) 2010 Fabian Heredia

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgment in the product documentation would be
   appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
   distribution.

===== Explanation =====
    The XOR cipher is based uppon boolean logic XOR. The cipher uses the 2
strings[plain & key] to safely encrypt the first(bit by bit).
Table:
---------------
| A | B | XOR |
| 0 | 0 |  0  |
| 0 | 1 |  1  |
| 1 | 0 |  1  |
| 1 | 1 |  0  |
---------------
    If you have acces to at least two of the three [plain, key, ciphered]
the remaining one is no longer protected. It is recommended to use a key
at most once since an attacker could start seeing patterns.
--------------------------------------------------------------------------------*/
#include <iostream>
#include <iomanip>
#include <fstream>
#include <limits.h>
#define MAX_LEN 128
using namespace std;

// Cipher explained avobe.
char* cipher(char* toCrypt, char* key)
{
    for(unsigned int i = 0, j = 0; i < sizeof(toCrypt); i++)
    {
        toCrypt[i] ^= key[j];
        j = (j + 1) % sizeof(key);
    }
    return toCrypt;
}

// Function for writing into a file.
void write(char* toWrite, char* file)
{
    ofstream out(file, ios::binary);
    if(out.is_open())
    {
        for(unsigned int i = 0; i < sizeof(toWrite); i++)
        {
            out << toWrite[i];
        }
        out.close();
    }
}

int main(int argc, char *argv[]){
    // If we recieve exactly 3 arguments.[Plain, Key, ,and Output file]
    /*if(argc == 4)
    {
        if(write(cipher(argv[1], argv[2]), argv[3]))
        {
            cout << "FAILED";
        }
    }*/
    // If we recieve exactly 2 arguments.[File and Key]
    /*else */if(argc == 3)
    {
        // TODO: File Manipulation
    }
    else if(argc > 1)
    {
        cout << argv[0] << endl;
        cout << "Usage:" << endl;
        cout << "\t1) 0 arguments - Utility for ciphering a file/text." << endl;
        cout << "\t2) 2 Arguments - [File to cipher] and [key]" << endl;
        cout << "\t3) 3 Arguments - [Plain], [key], and [output file]." << endl;
    }
    // If we recieve no arguments
    else
    {
        char *plain, *key, *out;
        plain = new char[MAX_LEN], key = new char[MAX_LEN], out = new char[MAX_LEN];
        cout << "File: ";
        cin >> setw(MAX_LEN) >> out;
        cin.ignore(INT_MAX, '\n');
        ifstream file(out, ios::binary);
        if(file.is_open())
        {
            cout << "Key: ";
            cin >> setw(MAX_LEN) >> key;
            cin.ignore(INT_MAX, '\n');
            // Loading file contents to memory.
            unsigned long size = file.tellg();
            char *mem;
            mem = new char[size];
            file.seekg (0, ios::end);
            file.read(mem, size);
            file.close();
            // Writing and cleaning up.
            write(cipher(mem, key), out);
            delete[] mem;
        }
        else
        {
            cout << "Plain: ";
            cin >> setw(MAX_LEN) >> plain;
            cin.ignore(INT_MAX, '\n');
            cout << "Key: ";
            cin >> setw(MAX_LEN) >> key;
            cin.ignore(INT_MAX, '\n');
            write(cipher(plain, key), out);
        }
        delete [] plain;
        delete [] key;
        delete [] out;
    }
    return 0;
}

It compiles and runs but does not work as expected. Again I am losing data when ciphering/writing.
@thetan, I will make that commit for the next revision.(Which I am doing atm)

-- Thu Nov 04, 2010 6:59 pm --

BTW, do I have any memory leaks?
Donate bitcoins to me! [1DhRP3hHgmSLQdRTZyT8VPTmzAj7Z2rsGA]
Dunno what bitcoins are? BitcoinMe
fabianhjr
Poster
Poster
 
Posts: 286
Joined: Tue Sep 21, 2010 7:48 pm
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by thetan on Fri Nov 05, 2010 1:34 am
([msg=48574]see Re: XOR cipher help - fstream binary wrting[/msg])

The problem is the way you're getting the size/length of the key string. sizeof(key) is synonymous for sizeof(char*). You want strlen() instead.

something to this effect:
Code: Select all
char* cipher(char* toCrypt, char* key)
{
    int keyLen = strlen(key);
    for(int i = 0; *toCrypt; ++toCrypt)
    {
        *toCrypt ^= key[i++];
        i %= keyLen;
    }
    return toCrypt;
}

should do, untested, but at least the point is conveyed.

fabianhjr wrote:BTW, do I have any memory leaks?

None that are blatantly obvious, run the program against valgrind and it should let you know if you have any it comes across during the course of execution.
"If art interprets our dreams, the computer executes them in the guise of programs!" - SICP

Image

“If at first, the idea is not absurd, then there is no hope for it” - Albert Einstein
User avatar
thetan
Contributor
Contributor
 
Posts: 657
Joined: Thu Dec 17, 2009 6:58 pm
Location: Various Bay Area Cities, California
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by fabianhjr on Sun Nov 07, 2010 10:55 pm
([msg=48710]see Re: XOR cipher help - fstream binary wrting[/msg])

Mhhh, not even chars are doing it.
Code: Select all
/*--------------------------------------------------------------------------------
===== Copyright =====
Copyright (c) 2010 Fabian Heredia

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

   1. The origin of this software must not be misrepresented; you must not
   claim that you wrote the original software. If you use this software
   in a product, an acknowledgment in the product documentation would be
   appreciated but is not required.

   2. Altered source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

   3. This notice may not be removed or altered from any source
   distribution.

===== Explanation =====
    The XOR cipher is based uppon boolean logic XOR. The cipher uses the 2
strings[plain & key] to safely encrypt the first(bit by bit).
Table:
---------------
| A | B | XOR |
| 0 | 0 |  0  |
| 0 | 1 |  1  |
| 1 | 0 |  1  |
| 1 | 1 |  0  |
---------------
    It is recommended to use a key at most once since an attacker could start
seeing patterns.(Frequency Analysis) It is also recommended that the length of
the key is equal or more than  the length of the plain.
--------------------------------------------------------------------------------*/
#include <iostream>
#include <iomanip>
#include <string.h>
#include <fstream>
#include <limits.h>
#define MAX_LEN 512
using namespace std;

// Cipher explained avobe.
char* cipher(char* toCrypt, const char* key)
{
    for(unsigned long i = 0; i < strlen(toCrypt); i++)
    {
        toCrypt[i] ^= key[i % strlen(key)];
    }
    return toCrypt;
}

// Function for writing into a file.
void write(const char* toWrite, const char* file)
{
    ofstream out(file, ios::binary);
    if(out.is_open())
    {
        out << toWrite;
        out.close();
    }
}

void cryptFile(char* fileName, char* key)
{
    fstream out(fileName, ios::binary);
    unsigned long size = out.tellg();
    char *mem;
    mem = new char[size];
    out.seekg(0, ios::end);
    out.read(mem, size);
    out.close();
    // Writing and cleaning up.
    write(cipher(mem, key), fileName);
    delete[] mem;
}

int main(int argc, char *argv[]){
    // If we recieve 3 arguments.[Plain, key, and file]
    if(argc > 3)
    {
        write(cipher(argv[1], argv[2]), argv[3]);
    }
    // If we recieve exactly 2 arguments.[File and Key]
    else if(argc > 2)
    {
        cryptFile(argv[1], argv[2]);
    }
    // Help message!
    else if(argc > 1)
    {
        cout << argv[0] << endl;
        cout << "Usage:" << endl;
        cout << "\t1) 0 arguments - CLI Wizard for ciphering a file/text." << endl;
        cout << "\t2) 2 Arguments - [File to cipher] and [key]" << endl;
        cout << "\t3) 3 Arguments - [Plain], [key], and [output file]." << endl;
    }
    // If we recieve no arguments
    else
    {
        // Var Declaration
        char *plain, *key, *out;
        plain = new char[MAX_LEN], key = new char[MAX_LEN], out = new char[MAX_LEN];
        // File to manipulate
        cout << "File: ";
        cin >> setw(MAX_LEN) >> out;
        cin.ignore(INT_MAX, '\n');
        // If it exsists we ask for a pass to crypt.
        ifstream file(out, ios::binary);
        if(file.is_open())
        {
            cout << "Key: ";
            cin >> setw(MAX_LEN) >> key;
            cin.ignore(INT_MAX, '\n');
            cryptFile(out, key);
        }
        // Else we ask for a plain message and a key to write into a file.
        else
        {
            cout << "Plain: ";
            cin >> setw(MAX_LEN) >> plain;
            cin.ignore(INT_MAX, '\n');
            cout << "Key: ";
            cin >> setw(MAX_LEN) >> key;
            cin.ignore(INT_MAX, '\n');
            write(cipher(plain, key), out);
        }
        delete [] plain;
        delete [] key;
        delete [] out;
    }
    return 0;
}


I added a cout << toCrypt; Before and after the for loop of the cipher. It looks like it is how it handles char* that would be terminated by a space or other special characters?! Also, now if I try to cryptFile() Windows Complaints and exits the program. :(

So far I improved the cipher.(Which is more readable) and added a function to clear some main() space.

thetan thanks for your support so far. :D
Donate bitcoins to me! [1DhRP3hHgmSLQdRTZyT8VPTmzAj7Z2rsGA]
Dunno what bitcoins are? BitcoinMe
fabianhjr
Poster
Poster
 
Posts: 286
Joined: Tue Sep 21, 2010 7:48 pm
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by thetan on Wed Nov 10, 2010 2:05 pm
([msg=48787]see Re: XOR cipher help - fstream binary wrting[/msg])

Seeing how i cant really stand C++ much, i just rewrote the entire thing in C. Everything seems to be in working order from a few trial runs. Have fun porting it all to nasty ass C++ :)

Code: Select all
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int get_file_size(char *file)
{
    struct stat statb;
    return (!stat(file, &statb)) ? (int) statb.st_size : -1;
}

// Cipher explained above.
char* cipher(char* toCrypt, int clen, char* key)
{
    int i, len = strlen(key);
    for(i = 0; i < clen; i++)
    {
        toCrypt[i] ^= key[i % len];
    }
    return toCrypt;
}

// Function for writing into a file.
int dump(char* toWrite, int size, char* file)
{
    int fd = open(file, O_WRONLY|O_CREAT);
   
    if (fd == -1)
    {
        fprintf(stderr, "failed opening file\n");
        return 0;
    }
   
    write(fd, toWrite, size);

    return 1;
}

int cryptFile(char* fileName, char* key)
{
    char *contents;
    int fd, size, pagesize;

    if ((size = get_file_size(fileName)) == -1)
    {
        fprintf(stderr, "No such file diqhed!\n");
        return 0;
    }

    if (!(fd = open(fileName, O_RDWR)))
    {
        fprintf(stderr, "wooops, cant open that file.\n");
        return 0;
    }

    pagesize = size + (size % getpagesize());
    contents = mmap((caddr_t)0, pagesize, PROT_READ | PROT_WRITE,
                    MAP_SHARED, fd, 0);
                   
    if (contents == (char*) -1)
    {
        fprintf(stderr, "god damnit, mmap b0rked on us\n");
        return 0;
    }

    cipher(contents, size, key);
   
    if (msync(contents, size, MS_SYNC) == -1)
    {
        fprintf(stderr, "Failed flushing data to disk\n");
        return 0;
    }
   
    munmap(contents, pagesize);
   
    return 1;
}

int main(int argc, char *argv[])
{
    switch (argc)
    {
        default:
        case 2: //........................................Help message!
            printf("%s\n"
                   "Usage:\n"
                   "\t1) 0 arguments - CLI Wizard for ciphering a "
                   "file/text.\n"
                   "\t2) 2 Arguments - [File to cipher] and [key]\n"
                    "\t3) 3 Arguments - [Plain], [key], and "
                    "[output file].\n", argv[0]);
            break;
           
        case 3: //.....If we recieve exactly 2 arguments.[File and Key]
            printf("encrypting file\n");
            cryptFile(argv[1], argv[2]);
            break;
           
        case 4: //.....If we recieve 3 arguments.[Plain, key, and file]
            printf("encrypting arguments\n");
            int size = strlen(argv[1]);
            dump(cipher(argv[1], size, argv[2]), size, argv[3]);
            break;         
    }
    return 0;
}
"If art interprets our dreams, the computer executes them in the guise of programs!" - SICP

Image

“If at first, the idea is not absurd, then there is no hope for it” - Albert Einstein
User avatar
thetan
Contributor
Contributor
 
Posts: 657
Joined: Thu Dec 17, 2009 6:58 pm
Location: Various Bay Area Cities, California
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by fabianhjr on Wed Nov 10, 2010 7:06 pm
([msg=48793]see Re: XOR cipher help - fstream binary wrting[/msg])

thetan, apples elped me figure out strlen() was getting Null Byte poisoned.
Now I am porting everything to use vector<char>. I will post back when I archieve it. :)

Thanks Thetan!
Donate bitcoins to me! [1DhRP3hHgmSLQdRTZyT8VPTmzAj7Z2rsGA]
Dunno what bitcoins are? BitcoinMe
fabianhjr
Poster
Poster
 
Posts: 286
Joined: Tue Sep 21, 2010 7:48 pm
Blog: View Blog (0)


Re: XOR cipher help - fstream binary wrting

Post by tgoe on Wed Nov 10, 2010 10:01 pm
([msg=48794]see Re: XOR cipher help - fstream binary wrting[/msg])

vectors, eh?

Image
(jesus tap dancing christ)

If you can't and don't write this in C, you have no business fiddling with C++.

Null Byte Poisoning? No.
Again, you're working with bytes... not just strings ('strings' are a subset of bytes...). How do you expect to encrypt, say, an image or program instead of just the "abc123" test file?
User avatar
tgoe
Contributor
Contributor
 
Posts: 668
Joined: Sun Sep 28, 2008 2:33 pm
Location: q3dm7
Blog: View Blog (0)


Next

Return to C and C++

Who is online

Users browsing this forum: No registered users and 0 guests