Thread: XOR Encryption

  1. #1
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183

    XOR Encryption

    Hi, I created a program that will read the text file you specify, and encrypt it with the key you specify. The encrypting stage works just fine, and the encrypted text is successfully saved to another text file. I've even tried decrypting it right after I've encrypted it in the same program, and it outputs the correct information. But if I close the program, and open again and try to decrypt it using the same key it either gives me a few of the words or just a mix of them, especially on long text files. I know that the problem is when it's reading it, but I don't know what else to do. Can anyone help me? Thanks. The code is below:

    Code:
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    #include <string.h>
    using namespace std;
    using std::string;
    
    string XOR(string value,string key)
    {
        string retval(value);
        int klen = key.length();
        int vlen = value.length();
        int k = 0, v = 0;
        
        for(v; v < vlen; v++)
        {
            retval[v] = value[v]^key[k];
            k = (++k < klen);
        }
        
        return retval;
    }
    
    int main()
    {
        string value;
        string key;
        char file[256];
        cout << "Please enter the key:\n";
        cin >> key;
        cout << "Please enter the name of the file to encrypt:\n";
        cin >> file;
        ifstream read(file);
        getline(read, value, 'X');
        value = XOR (value, key);
        cout << "Data being encrypted...\n";
        cout << "Done!\n";
        ofstream os("Encrypted_Text.txt");
        os << value;
    }

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Since the encrypted file is not essentially a text file ('\n' needn't mean end-of-line), but a binary file, this is how you'll need to read and write it.

    (In text files '\n' may actually represent a combination of characters which would be different for each OS.)

    Code:
    k = (++k < klen);
    This looks bad. k is assigned a boolean (0 or 1 - basically 1 every time?). And if it didn't this smells of the classical undefined behaviour example:
    Code:
    k = ++k; //wrong
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183
    Yeah the actual encryption part I got off of another site, so I don't really know a lot about it. I wrote the rest of it though.

  4. #4
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183
    Really, though, the only problem I have is reading the from the text file. It works just fine to decrypt the string while in the program and upon displaying it, it looks exactly as it should. However, when it's read is when it doesn't work- it just doesn't read it very much!

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    That is because the encrypted output is full of control characters, which means that you need to make sure that you read the file as a binary file, not as a text-file when you read the encrypted content.

    getline, for example, is not a "binary" function, it will for example stop reading when it comes to a "newline". If we take a simple case of text:
    ABCDEFGHIJKL
    and the key being "A":
    the bytes in the output will be:
    0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0B, 0x0A, 0x0D

    So the first problem is that you are using "X" as termination on your getline, which you may not find in the line when reading from the encrypted file.

    Second problem is that the above string contains a newline (0x0A) which will be treated as a "special" character...

    There are potentially other problems in your code as well, but those are major parts.

    Try using "read" and "write" to the file instead, and if you are using a Windows machine to run this code, add "ios:binary" to the stream constructor calls.

    --
    Mats

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
    k = (++k < klen);
    This clever line makes your encryption use either the first or the second character of the key.

    What you want should be more like
    Code:
    if (++k == klen)
        k = 0;
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183
    That is because the encrypted output is full of control characters, which means that you need to make sure that you read the file as a binary file, not as a text-file when you read the encrypted content.

    getline, for example, is not a "binary" function, it will for example stop reading when it comes to a "newline". If we take a simple case of text:
    ABCDEFGHIJKL
    and the key being "A":
    the bytes in the output will be:
    0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0B, 0x0A, 0x0D

    So the first problem is that you are using "X" as termination on your getline, which you may not find in the line when reading from the encrypted file.

    Second problem is that the above string contains a newline (0x0A) which will be treated as a "special" character...

    There are potentially other problems in your code as well, but those are major parts.

    Try using "read" and "write" to the file instead, and if you are using a Windows machine to run this code, add "ios:binary" to the stream constructor calls.

    --
    Mats
    So how exactly do I do that?

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by mikeman118 View Post
    So how exactly do I do that?
    Do you really want me to tell you? You don't think it's better if:
    A) You learn something by looking up how those functions are documented
    B) You feel the great joy of actually succeeding in this task.

    Also, this smells very much like a school assignment/homework, which this forum has a policy against "helping with". We can help get you in the right direction, but we should not do your work for you.

    --
    Mats

  9. #9
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183
    Do you really want me to tell you? You don't think it's better if:
    A) You learn something by looking up how those functions are documented
    B) You feel the great joy of actually succeeding in this task.

    Also, this smells very much like a school assignment/homework, which this forum has a policy against "helping with". We can help get you in the right direction, but we should not do your work for you.

    --
    Mats
    Oh sorry if it sounded that way, let me clear things up. I did try, it doesn't work, and I'll put the code on. I am a kid in grade school trying to learn C++, and I took a detour. I haven't even started school yet. If you don't want to help me, then I understand, but if you do, here's what I was trying. BTW, I'm still a beginner so that's why i may be making a really obvious mistake:


    Code:
    #include <iostream.h>
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    using std::string;
    int main()
    {
        char key[128];
        char string[99999];
        char filename[128];
        char out[99999];
        int length;
        cout << "Enter the key:\n";
        cin >> key;
        cout << "Please enter the name and path of the file to encrypt/decrypt:\n";
        cin >> filename;
        ifstream is;
        is.open (filename, ios::binary );
        is.seekg (0, ios::end);
        length = is.tellg(); 
        is.seekg (0, ios::beg);
        is.read (string, length);
        is.close();
        int i = sizeof(string);
        int kk = sizeof(key);
        int k;
        k < kk;
        for(int x = 0; x < i; x++)
        {
            k++;
            out[x] = string[x]^key[k];
        }
        cout << string << endl;
        system("pause");
    }

  10. #10
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    http://www.cplusplus.com/reference/i...ream/read.html

    Look at the example it might help you out

  11. #11
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183
    BTW, if you think I should just give this up and do something else, just tell me. All I really need to know is how to read an entire text file.

  12. #12
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183
    Quote Originally Posted by prog-bman View Post
    http://www.cplusplus.com/reference/i...ream/read.html

    Look at the example it might help you out
    Well actually that's what I did look at, but I don't really know if it helped me- I used that exact code in my code two posts ago, but with different variable names.

  13. #13
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    Is your goal to xor everything in the file including newlines? Or do you just want to xor the human readable items?

  14. #14
    Registered User mikeman118's Avatar
    Join Date
    Aug 2007
    Posts
    183
    Well if anyone's still actually paying attention to this thread, I fixed it where it doesn't generate an error, however, it's still not encrypting/decrypting right; I even used "read" this time:

    Code:
    #include <iostream.h>
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    using std::string;
    int main()
    {
        char key[128];
        char string[99999];
        char filename[128];
        char out[99999];
        int length;
        cout << "Enter the key:\n";
        cin >> key;
        cout << "Please enter the name and path of the file to encrypt/decrypt:\n";
        cin >> filename;
        ifstream is;
        is.open (filename, ios::binary );
        is.seekg (0, ios::end);
        length = is.tellg();  // get length of file:
        is.seekg (0, ios::beg);
        is.read (string, length); // read data as a block:
        is.close();
        int klen = sizeof(key);
        int vlen = sizeof(string);
        int k = 0, v = 0;
        for(v; v < vlen; v++)
        {
            out[v] = string[v]^key[k];
            k = (++k < klen);
        }
        ofstream os("Encrypt.txt");
        os << out;
        system("pause");
    }

  15. #15
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    Code:
    char string[99999];
    char out[99999];
    char key[128];
    why not use the string class? don't call a variable string, the string class already has that name.
    Last edited by robwhit; 08-08-2007 at 06:40 PM.

Popular pages Recent additions subscribe to a feed