Thread: Bitwrap

  1. #1
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209

    Bitwrap

    Good day,

    I'm attempting to write a short encryption program. One stage of the encryption / decryption process will be bitshifting. However, this process ( using << and >> operators ) causes data corruption : the end bit is lost. I wish to make sure that, whether the bit added when the program is run, is a 0 or a 1, that my code will work. Therefore, I have put together the following program :



    THEORY :

    Encryption
    Left bitshift by 1 bit. Endbit is lost. If endbit ( left bit representing 128 ) is 1, the value of character is bigger than 127. Therefore, if this is the case, bitshift 1 left, and then OR the value with the integer 1 ( 00000001 ) to wrap this bit on the end. This will correct the bitshift, whether the added bit on the right is a 1 or a 0.
    If the value of the character is less than 128, then bitshift left, and check if this new value is odd. If it is, take away 1, else, do nothing. This will correct the value of the bitshifted char, whether the added bit was 1 or 0.

    Decryption
    Right bitshift by 1 bit. Endbit ( right bit representing 1 ) is lost. If the value of the character is odd, then the endbit = 1. In this case, bitshift right, and check if the new value is larger than 127. If so, the added bit was 1, so do nothing. If it is less than 128, add 128 to the ASCII value in order to turn the added bit to 1.
    If the value is even, the new bit must be 0. Therefore, check, as above, if the new value, once bitshifted, is larger than 127. If this is the case, subtract 128. Else, do nothing. This will make sure the added bit is 0.



    PRACTICE :
    Code:
    void bse()   // BitShift Encrypt
    {
         int b = (int)a;   // a is char a; the character being encrypted.
         
         if(b > 127)
         {   
                 a = (a << 1);
                 a = (a | 1);
         }
         
         else if(b < 128)
         {
              a = (a << 1);
              if(a % 2 == 1) a = a - 1;
         }
    }
    
    
    
    
    
    
    
    void bsd()    // BitShift Decrypt
    {
         int b = (int)a;
         
         if((b % 2) == 1)
         {
               a = (a >> 1);
               int c = (int)a;
               if(c < 127) a = a + 128;
         }
         
         else if((b % 2) == 0)
         {
              a = (a >> 1);
              int c = (int)a;
              if(c > 127) a = a - 128;
         }
    }

    For some reason that escapes me, this code only works for ASCII values larger than 127, and I cannot see the problem...

    Korhedron

  2. #2
    Registered User
    Join Date
    Jun 2005
    Location
    Philadelphia
    Posts
    16
    Might be wrong, but isnt it always a 0 thats added in bit shift?

  3. #3
    Hardware Engineer
    Join Date
    Sep 2001
    Posts
    1,398
    I haven't studied your code thoroughly, but something's weird here:
    Code:
    a = (a << 1);
    if(a % 2 == 1) a = a - 1;
    After you bit-shift left, the number will always be even. You are probably supposed to perform the full bit-rotate here, not just a bit-shift.

    The assignment-instructions are almost step-by-step psudo code... If this was my assignment, I would split-up the instructions (one line per instruction) and copy them into the program as comments. That would make it easier to see if the code really follows the logic.
    Last edited by DougDbug; 06-10-2005 at 06:46 PM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Code:
    b = ((b<<1)&0xFE) | ((b>>7)&0x01);
    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
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    Thank you for all the replies...

    I still have a few questions.
    Firstly, RedZone, I thought that 0 was always added, yet the code above is supposed to be able to work whether a 0 or a 1 was added... When bitshifting left, the test determines whether the lost bit was 1 or 0, and then makes sure the added bit corresponds. When bitshifting right, the same thing is done : the lost bit is determined, and then we make sure the added bit corresponds. Therefore, why does this only work for ASCII values above 128 ?

    DougDBug, thanks for the comments. I'm aware that my code is hardly presentable :P

    Salem, thanks for the alternative, which I'm still trying to work out

    I'll post my progress as soon as possible.

    Thanks,
    Korhedron

  6. #6
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    The code seems to work, except now, for values above 128. I think this is because my tests have been using Notepad, which won't take Unicode characters ( and, for example, the character é which has an ASCII value of 130, bitwraps left to have an ASCII value of 5, which Notepad won't take ). However, I've tested this with MSWord Documents, or with JPG images, and still, the outputted file has changes and won't open properly. I'm not sure what's going wrong...

    Currently, I'm doing this :

    Code:
    void bse()
    {
         int b = (int)a;
         if(b > 127)
         {
             a = ((a << 1) | 0x01);  // If the lost bit was 1, make sure it's 1 on the right after bitshift
         }
         
         else
         {
             a = ((a << 1) & 0xFE);   // If lost bit was 0, make sure it's 0 after bitshift
         }
    }
    
    
    void bsd()
    {
         if( ((int)a) % 2 == 1)
         {
             a = ((a >> 1) | 0x80);
         }
         
         else
         {
             a = ((a >> 1) & 0x7F);
         }
    }

    I'm therefore thinking the code works, but file formats won't take certain characters. I've tried files with no extension, same problem : chars with ASCII over 128 won't convert properly... Any ideas ?

    Thanks,
    Kor

  7. #7
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    Code:
    b = ((b<<1)&0xFE) | ((b>>7)&0x01);
    This is not hard to work out at all. Lets split it up a little.

    whats the bit pattern of 0xFE?
    it looks like this....
    11111110
    This is a mask. First b is left shifted 1 bit. That means each bit is moved up into the next highest bit and a zero is placed in the least significant bit. The most significant bit is lost.We then bitwise and the temporary that holds our bitshifted b with the mask.This has the effect of preserving the top 7 bits and clearing the least significant bit.
    Now the other side of the or. This time we make a temporary with the most significant bit shifted all the way to become the least significant bit. We then and it with this bit pattern....
    00000001
    This clears the top seven bits and preserves the least significant bit(which used to be the msb).
    Finally the shifted left 1 place temporary is binary ored with the temporary that holds our msb shifted to lsb.This has the effect of combining the two halfs. Finally that result is assigned to b.
    This does a byte bit rotation.
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  8. #8
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    Stoned_Coder, thanks for the explanation, I had missed the fact that all bits except the least significant bit would be cleared in the second part.

    This solves my problem, and is by far a more efficient way of bitwrapping my characters. However, it seems this will still cause a problem : I cannot use this to encrypt data, as certain ASCII values aren't characters but control keystrokes ( such as '\a' which cannot be printed in a file ). I was therefore wondering if anyone knew a way to solve this problem, to be able to use bitwrapping in an encryption algorithm...

    Thanks for everyone's help !
    Korhedron
    Last edited by Korhedron; 06-11-2005 at 07:34 AM.

  9. #9
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    Use binary i/o not text i/o
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  10. #10
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    I am currently using binary I/O, still to the same effect... é ( ASCII 130 ) becomes ASCII 5 which won't print or save to file.

  11. #11
    Skunkmeister Stoned_Coder's Avatar
    Join Date
    Aug 2001
    Posts
    2,572
    post your i/o routines. Lets see whats going on.
    Free the weed!! Class B to class C is not good enough!!
    And the FAQ is here :- http://faq.cprogramming.com/cgi-bin/smartfaq.cgi

  12. #12
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    Code:
    ifstream fin;
    ofstream fout;
    
    fin.open("text.txt", ios::binary);
    fout.open("out.txt", ios::binary);
    
    while(fin.get(a))
    {
         bse();
         fout << a;
    }
    That's all I'm doing... I've tried with files with no extension, to the same result.

  13. #13
    Registered User
    Join Date
    Jun 2004
    Posts
    722
    Quote Originally Posted by Korhedron
    Code:
    if(a % 2 == 1) a = a - 1;
    this is the same as this
    Code:
    a &= ~1;
    in words, if there's a less significant 1, change it to zero, always

    Quote Originally Posted by Korhedron
    Code:
    ifstream fin;
    ofstream fout;
    
    fin.open("text.txt", ios::binary);
    fout.open("out.txt", ios::binary);
    
    while(fin.get(a))
    {
         bse();
         fout << a;
    }
    That's all I'm doing... I've tried with files with no extension, to the same result.
    lool, you're not passing your read char to the function
    Code:
    void bse(int& a)
    {
        a = ((a<<1) &0xfe )| ( (a>>7) &1 );
    }
    
    
    void bsd(int& a)
    {
        a = ((a>>1) &0x7f )| ( (a<<7) &0x80 );
    }
    
    /*********************************/
    ifstream fin;
    ofstream fout;
    
    fin.open("text.txt", ios::binary);
    fout.open("out.txt", ios::binary);
    
    while(fin.get(a))
    {
         bse(a);
         fout << a;
    }
    Last edited by xErath; 06-11-2005 at 09:19 AM.

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > the character é which has an ASCII value of 130, bitwraps left to have an ASCII value of 5, which Notepad won't take
    Yeah, you really need a hex editor to view the output files of your program to stand any chance of seeing what's happening.
    That way, you can see what each byte really is.
    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.

  15. #15
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    Thanks for the help, I'll get a hex editor. Other than that though, I can't really use this in any kind of algorithm, or I'd have some kind of data loss if I compensated for unprintable characters... Thanks anyway

    xErath, my char a is a global variable, thus is passed to the function when it calls it.

    Thanks a lot,
    Korhedron

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Bitwrap problems
    By Korhedron in forum C++ Programming
    Replies: 15
    Last Post: 09-10-2005, 04:56 PM