Thread: xor Encryption

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    7

    xor Encryption

    I am trying to work out the encryption function to the following decryption function.

    Code:
    char* buf;
    	unsigned int nKey = buf[3] << 24;
    	nKey |= buf[2] << 16;
    	nKey |= buf[1] << 8;
    	nKey |= buf[0];
    	unsigned int nIndex = 4;
    
    	for(unsigned int nBitNr = 0; nBitNr < 32; ++nBitNr, nIndex++)
    	{
    		int nDecryptBit = (nKey & (1 << nBitNr)) >> nBitNr;
    		int chEncryptedByte = buf[nIndex];
    		int chDecryptedByte = chEncryptedByte;
    
    		chDecryptedByte = chDecryptedByte ^ nDecryptBit;
    		chDecryptedByte = chDecryptedByte & 1;
    		chDecryptedByte = chDecryptedByte ^ chEncryptedByte;
    		buf[nIndex] = chDecryptedByte;
    		if(nBitNr == 31)
    			break;
    	}
    	printf("File Decrypted is %s\n",buf);
    I see that the decrpt key is the first for bytes of Buf and that only 32 bytes are decrypted.

    From searching these forums I now know that
    a = b ^ c goes to c = b ^ a

    would a = b & 1 go to a = b & 0?

    also what is this doing?
    Code:
    int nDecryptBit = (nKey & (1 << nBitNr)) >> nBitNr;
    Last edited by cruxis; 11-05-2004 at 04:42 PM.

  2. #2
    Registered User
    Join Date
    Mar 2003
    Posts
    143
    This is a fairly badly coded function that performs a fairly bad encryption scheme.
    To answer your last question first:
    Code:
     
    int nDecryptBit = (nKey & (1 << nBitNr)) >> nBitNr;
    /* can be written */
    int nDecryptBit = (nKey >> nBitNr) & 1;
    gets the value of a single bit in nKey which is bit number nBitNr counting from the least significant bit where the least significant bit is number 0.

    a=b & 1 clears all but the least significant bit of a. the lsb of a = lsb of b. There is no inverse.

    If you work out the logic of what the rest of the code does - it just replaces the least significant bit of the encrypted bit with the corresponding bit in the key. So your encoding algorithm should create the key out of the least significant bits of the plain text and, I would suggest, randomly toggle the lsb of the rest of the message:
    Code:
    key[i/8] = (key[i/8] << 1) | (plaintextByte[i] & 1);
    encryptedByte[4+i] = plaintextByte[i] ^ (rand() % 2);
    or something similar...

    ::edit:: ah, no, the key calculation gets the bits the wrong way round - but I'll leave that as an exercise for the reader (as they say in all the best text books!)...
    Last edited by DavT; 11-05-2004 at 07:43 AM.
    DavT
    -----------------------------------------------

  3. #3
    Registered User
    Join Date
    Sep 2004
    Posts
    7
    Whats that /8? , The last bit of the byte
    Ive tried making the encryption to that decryption function. Heres my attempt.
    Encryption is not really what it is I assume just some mangling of data.

    Code:
    	unsigned int nIndex = 4;
    
    	for(unsigned int nBitNr = 0; nBitNr < 32; ++nBitNr, nIndex++)
    	{
    		// make key ???
    		unsigned int nKey = buf[nIndex] << 1 | (buf[nIndex] & 1);
    		
    		int nEncryptBit = (nKey >> nBitNr) & 1;
    
    	    int	chEncryptedByte = nEncryptBit ^ buf[4+nIndex]; 
    
    		buf[4+nIndex] = chEncryptedByte;
    
    		if(nBitNr == 31)
    			break;
    	}
    	printf("File Encrypted is %s\n",buf);
    I close, I think. Still quite dont know what is going on.

  4. #4
    Registered User
    Join Date
    Mar 2003
    Posts
    143
    The way to see if you are close is to try it out. I used this short program to test out your encoder:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    void decrypt (unsigned char buf[37])
    {
      unsigned int nBitNr;
      unsigned int nIndex = 4;
      unsigned int nKey = (unsigned int)buf[3] << 24;
      nKey |= (unsigned int)buf[2] << 16;
      nKey |= (unsigned int)buf[1] << 8;
      nKey |= (unsigned int)buf[0];
    
      for(nBitNr = 0; nBitNr < 32; ++nBitNr, nIndex++)
      {
        int nDecryptBit = (nKey & (1 << nBitNr)) >> nBitNr;
        int chEncryptedByte = buf[nIndex];
        int chDecryptedByte = chEncryptedByte;
    
        chDecryptedByte = chDecryptedByte ^ nDecryptBit;
        chDecryptedByte = chDecryptedByte & 1;
        chDecryptedByte = chDecryptedByte ^ chEncryptedByte;
        buf[nIndex] = chDecryptedByte;
        if(nBitNr == 31)
          break;
      }
      buf[36] = '\0';  /* added to make sure the string is properly terminated */
      printf("File Decrypted is %s\n",buf);
    }
    
    void cruxisEncrypt (char buf[37])
    {
      unsigned int nBitNr;
      unsigned int nIndex = 4;
    
      for(nBitNr = 0; nBitNr < 32; ++nBitNr, nIndex++)
      {
        // make key ???
        unsigned int nKey = buf[nIndex] << 1 | (buf[nIndex] & 1);
    
        int nEncryptBit = (nKey >> nBitNr) & 1;
    
        int	chEncryptedByte = nEncryptBit ^ buf[4+nIndex]; 
    
        buf[4+nIndex] = chEncryptedByte;
    
        if(nBitNr == 31)
    	    break;
      }
      printf("File Encrypted is %s\n",buf);
    }
    
    void davtEncrypt (char buf[37])
    {
      unsigned int i;
    
      for (i = 35; i > 3; i--) {
        buf[(i-4)/8] = (buf[(i-4)/8] << 1) | (buf[i] & 1);
        buf[i] ^= rand() % 2;
      }
      buf[36] = '\0'; /* shouldn't need this line - but just in case... */
      printf("File Encrypted is %s\n", buf);
    }
    
    int main (void)
    {
      char buf[37] = "key*This is my plaintext. How dull!!";
    
    //  davtEncrypt(buf);
      cruxisEncrypt(buf);
      decrypt(buf);
    
      return 0;
    }
    Notice that I have had to make some changes to the code to get it to compile - some because my compiler is pre-C99 and some because it just won't work. Here is what I get as output:
    Code:
    File Encrypted is key*This is my!plaintext. How dull!!
    File Decrypted is key*Uihs is mx!plainudxu/!Inv!dulm
    Which is clearly not right. Using my function gives:
    Code:
    File Encrypted is lce¬Tihs hs ly ql`ioudyu/!How dtll  
    File Decrypted is lce¬This is my plaintext. How dull!!
    Which shows that it works. (note that the first 4 symbols above are not right - I couldn't type the actual values produced by the program). All my code does is store the least significant bit of each character in the key and randomly mess up the least significant bit of each character in the message. The decrypt algorithm can be simplified to:
    Code:
    void decrypt (char buf[37])
    {
      unsigned int i;
    
      for (i = 0; i < 32; i++) {
        unsigned int keyBit = ((buf[i/8] >> (i%8)) & 1);
        buf[i+4] &= (~1); /* clear lsb */
        buf[i+4] |= keyBit; /* set lsb = keyBit */
      }
      buf[36] = '\0';
      printf("File Decrypted is %s\n", buf);
    }
    DavT
    -----------------------------------------------

  5. #5
    Registered User
    Join Date
    Nov 2004
    Posts
    17
    Whats that /8? , The last bit of the byte
    ..this is an index to the buf:

    Code:
    for (i = 0; i < 32; i++)
    unsigned int keyBit = buf[i/8];
    so that keyBit calculations are along this line:
    buf[0/8]
    buf[1/8]
    buf[2/8]
    ...
    buf[7/8]
    buf[8/8]
    ...
    buf[30/8]
    buf[31/8]


    It would be interesting to see what you're dealing with first to be going from "decryption" to "encryption".. can you post a message?

    I ran this code just to check it out even though this is beyond my understanding, but it doesn't seem like too complex of a problem.

    the results were pretty various depending on how you do it:

    Code:
    int main (void)
    {
      char buf[37] = "key*This is my plaintext. How dull!!";
    
    //  davtEncrypt(buf);
      cruxisEncrypt(buf);
    //  decrypt(buf);
      OriginalDecrypt(buf);
    
      return 0;
    }

    I know this for sure though:

    Code:
    AND:
           0100 1101
        &  0011 1011
           ---------
           0000 1001
    
    OR:
           0100 1101
        |  0011 1011
           ---------
           0111 1111
    
    XOR:
           0100 1101
        ^  0011 1011
           ---------
           0111 0110

  6. #6
    Registered User
    Join Date
    Nov 2004
    Posts
    17
    ok, I've come up with this.. I think it's right(but first time I've attempted insanity like that).

    Code:
    void OriginalDecrypt(char* buf)
    {
    	unsigned int nKey = buf[3] << 24;
    	nKey |= buf[2] << 16;
    	nKey |= buf[1] << 8;
    	nKey |= buf[0];
    	unsigned int nIndex = 4;
    
    	for(unsigned int nBitNr = 0; nBitNr < 32; ++nBitNr, nIndex++)
    	{
    		//this pulls the # 'nBitNr' bit from the 32-bit key
    		//and shifts it to the bottom of int 'nDecryptBit'.
    		//So, the lsb holds the key bit from the relevant index of the key
    		int nDecryptBit = (nKey & (1 << nBitNr)) >> nBitNr;
    		//iteration 1
    		//int nDecryptBit = (nKey & (1 << 0)) >> 0;
    		//int nDecryptBit = (nKey &    1    ) >> 0;
    		//int nDecryptBit = (1:0 in first bit)>> 0;
    		//int nDecryptBit = (1:0 in first bit);
    
    		//iteration 2
    		//int nDecryptBit = (nKey & (1 << 1)) >> 1;
    		//int nDecryptBit = (nKey &    2    ) >> 1;
    		//int nDecryptBit = (nKey &    2    ) >> 1;
    		//int nDecryptBit = (1:0  &    2    ) >> 1;
    		//int nDecryptBit = (1:0 in second bit) >> 1;
    		//int nDecryptBit = (1:0 in first bit);
    
    		//iteration 3
    		//int nDecryptBit = (nKey & (1 << 2)) >> 2;
    		//int nDecryptBit = (nKey &    4    ) >> 2;
    		//int nDecryptBit = (nKey &    4    ) >> 2;
    		//int nDecryptBit = (1:0  &    4    ) >> 2;
    		//int nDecryptBit = (1:0 in third bit) >> 2;
    		//int nDecryptBit = (1:0 in first bit);
    
    		int chEncryptedByte = buf[nIndex];
    		int chDecryptedByte = chEncryptedByte;
    
    		//this XOR's the encrypted byte with decrypting bit from the key
    		//So, this is dealing with the lsb only(since nDecryptBit)
    		chDecryptedByte = chEncryptedByte ^ nDecryptBit;
    
    		//this will then clear all of the upper bits
    		//So, this is getting to only the lsb related
    		//between the key and encrypted-byte-lsb-bit
    		chDecryptedByte = chDecryptedByte & 1;
    
    		//this XOR's the decrypted mask byte(only lsb relevant)
    		//with the encrypted byte(only lsb relevant)
    		chDecryptedByte = chDecryptedByte  ^ chEncryptedByte;
    
    		//this puts the decrypted byte back into the buffer
    		buf[nIndex] = chDecryptedByte;
    
    		if(nBitNr == 31)
    			break;
    	}
    	printf("File Decrypted is %s\n",buf);
    }
    ..and from what I can realize it seems like this is what applies:

    -if key is 0 and char is even(0,2,4,etc.), then the char will stay the same
    -if key is 0 and char is odd, then the char will have 'encryption'
    -if key is 1 and char is even(0,2,4,etc.), then the char will have 'encryption'
    -if key is 1 and char is odd, then the char will stay the same

    so, if this is the case, then it makes me think about the encryption ordering in the first place. For example, in a case like DavT has presented with the randomized obsfucation of the bytes, how can the decryption know which bytes to affect? It would seem like the decryption would need to know the same random order to be able to decrypt properly.

    I wonder if there would be any relevance in looking at existing key structuring to realize some patternization there?

Popular pages Recent additions subscribe to a feed