Thread: XOR Encryption problem.

  1. #1
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313

    XOR Encryption problem.

    For the life of me, I cannot figure out why I can encrypt text, but not decrypt it.

    Here's the code, and I'll show you some sample output.

    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    
    std::string encrypt(char fname[255]);
    std::string decrypt(char fname[255]);
    
    int main(int argc, char *argv[])
    {
    	if (argc < 2)
    	{
    		std::cout << "\nThe correct usage is main.exe -[(e)ncrypt/(d)ecrypt/(h)elp].";
    				
    		std::cin.get();
    		return(0);
    	}
    	
    	if ((strcmp(argv[1], "-help") == 0) || (strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "-?") == 0))
    	{
    		std::cout << "\nAvailable options are -help (-h, -?), -encrypt (-e), and -decrypt (-d).";
    		std::cin.get();
    		return(0);
    	}
    	
    	else if ((strcmp(argv[1], "-encrypt") == 0) || (strcmp(argv[1], "-e") == 0))
    	{
    		encrypt("crypt.dat");
    	}
    	
    	else if ((strcmp(argv[1], "-decrypt") == 0) || (strcmp(argv[1], "-d") == 0))
    	{
    		decrypt("crypt.dat");
    	}
    	
    	std::cin.get();
    	return(0);
    }
    
    std::string encrypt(char filename[255])
    {
    	char buffer[65535];
    	const char key[9] = "CProgcom";
    	
    	std::ofstream oFile(filename, std::ios::binary | std::ios::trunc);
    	
    		std::cout << "\nInput text to be encrypted: ";
    		std::cin.getline(buffer, 65535, '\n');
    		
    		int y = 0;
    		
    		for (int x = 0; x < 65535; x++)
    		{
    			if (buffer[x] == '\0')
    			{
    				break;
    			}
    			
    			std::cout << buffer[x] << " . " << key[y] << " . ";
    			
    			buffer[x] = buffer[x]^(int)key[y];
    			y++;
    			
    			std::cout << buffer[x] << "\n";
    			
    			if (y >= 8)
    			{
    				y = 0;
    			}
    		}
    		
    		oFile << buffer;
    		
    	oFile.close();
    	return(0);
    }
    
    std::string decrypt(char fname[255])
    {
    	char buffer[65535];
    	const char key[9] = "CProgcom";
    	
    	std::ifstream iFile(fname, std::ios::binary);
    		
    		iFile.getline(buffer, 65535, '\n');
    		
    		int y = 0;
    		
    		for (int x = 0; x < 65535; x++)
    		{
    			if (buffer[x] == '\0')
    			{
    				break;
    			}
    			
    			std::cout << buffer[x] << " . " << key[y] << " . ";
    			
    			buffer[x] = buffer[x]^(int)key[y];
    			y++;
    			
    			std::cout << buffer[x] << "\n";
    			
    			if (y >= 8)
    			{
    				y = 0;
    			}
    		}
    		
    		std::cout << "\n" << buffer << "\n";
    	
    	iFile.close();
    	return(0);
    }
    Output from Encryption:

    Code:
    T . C . ↨
    h . P . 8
    i . r . ←
    s . o . ∟
      . g . G
    i . c .
    
    s . o . ∟
      . m . M
    a . C . "
      . P . p
    t . r . ♠
    e . o .
    
    s . g . ¶
    t . c . ↨
    . . o . A
    Output from Decryption:

    Code:
    ↨ . C . T
    8 . P . h
    ← . r . i
    ∟ . o . s
    G . g .
    Please help?

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    > oFile << buffer;

    > iFile.getline(buffer, 65535, '\n');

    You should use write() to output the buffer, and read() to input the buffer.

  3. #3
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313
    Thanks.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    If you pass a buffer (not a filename) to encrypt/decrypt, you should see that both functions are in fact the same.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313
    Quote Originally Posted by Salem
    If you pass a buffer (not a filename) to encrypt/decrypt, you should see that both functions are in fact the same.
    Heh, that's one of those "optimization" things that I still have a hard time seeing. -_-()

    Thanks Salem.

  6. #6
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313

    Well crap.

    I rewrote the two functions into one function (bloody ugly, I might add).. and it stopped working again. Perhaps I can get some help again?

    The problem is that I don't understand exactly why I can write and read from a file in binary, do the exact same XOR, and end up with two different outputs. :/

    Code:
    std::string crypt(std::string filename, int flag)
    {
    	std::string buffer, key("CProgramming");
    	
    	if (flag == 1)
    	{
    		std::cout << "\nInput text to be encrypted: ";
    		std::getline(std::cin, buffer, '\n');
    	}
    	
    	//std::cout << "\nInput passphrase: ";
    	//std::getline(std::cin, key, '\n');
    	
    	std::fstream File(filename.c_str(), std::ios::in | std::ios::binary);
    		if (flag == 2)
    		{
    			File.read(const_cast<char *>(buffer.c_str()), sizeof(buffer));
    		}
    	
    		int y = 0;
    		
    		for (int x = 0; x < 65535; x++)
    		{
    			if (buffer[x] == '\0')
    			{
    				break;
    			}
    			
    			buffer[x] = buffer[x]^key[y];
    			y++;
    			
    			if (y >= key.size())
    			{
    				y = 0;
    			}
    		}
    		
    		if (flag == 1)
    		{
    			File.close();
    			
    			std::fstream File(filename.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
    				File.write(buffer.c_str(), sizeof(buffer));
    			File.close();			
    		}
    		
    		else if (flag == 2)
    		{
    			std::cout << buffer;
    		}
    	File.close();
    	
    	return(0);
    }

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Why are you reading and writing binary at all? Since in your code you specificly treat everything as if it were a standard C string. Binary data can and often does have bytes containing nothing at all. This translates to a null when you try and make it a C string. Either use unsigned characters for reading in binary mode here, or don't use binary. Because as is, you're going to be doing it all wrong.

    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Registered User
    Join Date
    Aug 2004
    Location
    San Diego, CA
    Posts
    313
    Quote Originally Posted by quzah
    Why are you reading and writing binary at all? Since in your code you specificly treat everything as if it were a standard C string. Binary data can and often does have bytes containing nothing at all. This translates to a null when you try and make it a C string. Either use unsigned characters for reading in binary mode here, or don't use binary. Because as is, you're going to be doing it all wrong.

    Quzah.
    I've been trying to figure out what you mean when you say this, but everything I think of isn't making sense.

    Are you refering to std::stringstream, or something else?

  9. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,934
    I think if you're going to combine encrypt() and decrypt() into one subroutine, all the reading and writing to the file should be done in a separate subroutine. It's too compicated having a flag like you have.

    When encrypting, read in your text to buffer first in a read subroutine, then pass the buffer to crypt(), pass back the encrypted text, then write it to the file. When decrypting, read from the file into the buffer, then pass the buffer to crypt().

    Anyway, here's the crypt() you had with some changes to make it work.
    Code:
    void crypt(std::string filename, int flag)
    {
    	std::string buffer, key("CProgramming");
    	size_t length;
    	
    	if (flag == 1)
    	{
    		std::cout << "\nInput text to be encrypted: ";
    		std::getline(std::cin, buffer, '\n');
    		length = buffer.length();
    		std::cout << "length:" << length << std::endl;
    	}
    	
    	//std::cout << "\nInput passphrase: ";
    	//std::getline(std::cin, key, '\n');
    	
    	std::fstream File(filename.c_str(), std::ios::in | std::ios::binary);
    		if (flag == 2)
    		{
    			char buf[1000];
    			//File.read(const_cast<char *>(buffer.c_str()), sizeof(buffer));
    			File.read(buf, sizeof(buf));
    			length = File.gcount();
    			for (int i=0; i<length; i++)
    				buffer += buf[i];
    		}
    	
    		int y = 0;
    		
    		//for (int x = 0; x < 65535; x++)
    		for (size_t x = 0; x < length; x++)
    		{
    			//if (buffer[x] == '\0')
    			//{
    			//	break;
    			//}
    			
    			buffer[x] = buffer[x]^key[y];
    			y++;
    			
    			if (y >= key.size())
    			{
    				y = 0;
    			}
    		}
    		
    		if (flag == 1)
    		{
    			File.close();
    			
    			std::fstream File(filename.c_str(), std::ios::out | std::ios::binary | std::ios::trunc);
    				//File.write(buffer.c_str(), sizeof(buffer));
    				File.write(buffer.c_str(), buffer.length());
    			File.close();			
    		}
    		
    		else if (flag == 2)
    		{
    			std::cout << buffer << std::endl;
    		}
    	File.close();
    	
    	//return(0);
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM