Thread: Bitwrap problems

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

    Bitwrap problems

    Hello,

    I'm writing a (very very bad) encryption program. I wanted to use bitwrap in my program, but for some reason, it's not working, and I can't quite see where.

    Code:
    // from encrypt.h
    void encry(char* fileIN)
    {
         fin.open(fileIN, ios::binary);
         if(!fin) cout << "fin.ERROR";
         
         fout.open("temp.cry", ios::binary);
         if(!fout) cout << "fout.ERROR";
         
         while(fin.get(a))
         {
              a = a ^ key[x++];
              if(strlen(key) == x) x = 0;
              
              bsl();
              
              fout << a;
         }
         
         fin.close();
         fout.close();
    }


    Code:
    // bsl() - bitshift left. Code as follows.
    void bsl()
    {
         if(a > 127)
         {
              a = a << 1;
              a = a ^ 0x01;
         }
         
         if(a < 128)
         {
              a = a << 1;
              a = a & 0xFE;
         }
    }
    
    
    
    
    
    void bsr()
    {
         if(((int)a % 2) == 0)
         {
              a = a >> 1;
              a = a & 0x7F;
         }
         
         if(((int)a % 2) == 1)
         {
              a = a >> 1;
              a = a ^ 0x80;
         }
    }

    Obviously, the decrypting function bitshifts right before XORing. If I try to encrypt / decrypt a simple text file containing ABCDE, I realise that only B and D get decrypted correctly. I'm guessing this means I've got something wrong with ODD-numbered ASCII characters... But I can't see what.

    Thanks for your help.

  2. #2
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    If I understand your question correctly you don't want to bitshift the bits in a char, you want to rotate the bits.
    Try this:
    Code:
    #include <iostream>
    using namespace std;
    
    string byte_to_bin(unsigned char c) {
       unsigned char mask = 0x80;
       string ret;
       for ( int i = 0; i < 8; ++i ) {
          ret += ( c & mask ? "1": "0"); mask >>= 1;
       }
       return ret;     
    }
    
    unsigned char ror( unsigned char c ) {
      unsigned char ret = c;
      ret >>= 1;
      if ( c & 0x01 ) ret |= 0x80;
      return ret;
    }
    
    unsigned char rol( unsigned char c ) {
      unsigned char ret = c;
      ret <<= 1;
      if ( c & 0x80 ) ret |= 0x01;
      return ret;
    }
    
    int main() {
       unsigned char c = 89;
       cout << byte_to_bin(c) << "  >>" << endl;
       c = ror(c);
       cout << byte_to_bin(c) << endl;
       c = 155;
       cout << byte_to_bin(c) << "  <<" << endl;
       c = rol(c);
       cout << byte_to_bin(c) << endl;
       return 0;
    }
    Kurt
    Last edited by ZuK; 09-10-2005 at 06:32 AM.

  3. #3
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    There are easier ways to do this. Simply shoft in the desired direction, and then 'or' the remainder back onto the front (no testing required):
    Code:
    #include <cstddef>
    #include <iostream>
    #include <limits>
    
    template<typename T>
    T rot_left(T value, std::size_t amt)
    {
       return (value << amt) | (value >> std::numeric_limits<T>::digits - amt);
    }
    
    template<typename T>
    void print_bits(T value)
    {
       T mask = 1 << std::numeric_limits<T>::digits - 1;
       while(mask)
       {
          std::cout << (mask & value ? '1' : '0');
          mask >>= 1;
       }
       std::cout << std::endl;
    }
    
    int main()
    {
       unsigned char ch = 0x6f;
       print_bits(ch);
       ch = rot_left(ch, 5);
       print_bits(ch);
    }
    Cheers
    Last edited by Zach L.; 09-10-2005 at 07:23 AM.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  4. #4
    Registered User
    Join Date
    Nov 2002
    Posts
    491
    Why don't you pass 'a' to bsl rather than have it depend on a global variable of fairly poor naming convention?

  5. #5
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    Thank you for all your replies. Unfortunately, my level of C++ is hardly sufficient to work out your answers, and templates are so far too advanced for me.
    Besides which, I'd like to know the logic behind what's going wrong in my code. The theory behind it seems correct, and I can't figure out what's wrong...

    Thanks,
    Korhedron

  6. #6
    Toaster Zach L.'s Avatar
    Join Date
    Aug 2001
    Posts
    2,686
    Well, to eliminate the templates, you can simply remove 'template<typename T>' and replace 'T' with whatever type you are using (in my example, unsigned char).

    The theory in mine, is this:

    Say you have a binary number: 10010110
    Now, say you want to rotate it 3 places to the left, so partition it: (100)(10110)
    Now, you want to move the right half over three places, and replace the trailing bits with 0. The left shift operator does this, so we have an implicit 'temporary variable'* which gets: 10110000
    Now, we want to push the left half to the right to line it up with those new 0's and replace everything before it with 0's. Now, the amount we must shift it is the size of the data type (in bits) minus the number of bits we shift left, so we get another 'temporary variable' with: 00000100
    Now, to combine them, we use the bitwise or operator: |. We are guaranteed that each portion of or original piece of data is 'lined up' with the new 0's in the temporaries. We use or because (x | 0 == x) and this is a bitwise relation, giving us: 10110100

    *I use the terminology to explain the logic, not to represent how the compiler will actually do things.
    The word rap as it applies to music is the result of a peculiar phonological rule which has stripped the word of its initial voiceless velar stop.

  7. #7
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by Korhedron
    Besides which, I'd like to know the logic behind what's going wrong in my code. The theory behind it seems correct, and I can't figure out what's wrong...
    I'll try to explain what goes wrong
    Code:
    // bsl() - bitshift left. Code as follows.
    void bsl() {
         if(a > 127) {         // if bit 7 set
              a = a << 1;      // shift left 1 bit
              a = a ^ 0x01;    // set bit 0
         }                          
         if(a < 128) {         // if  bit 7 not set
              a = a << 1;      // shift left 1 bit
              a = a & 0xFE;    // clear bit 7
         }                     // don't do that
    }
    
    void bsr() {
         if(((int)a % 2) == 0){  // if bit 0 not set
              a = a >> 1;        // shift right
            //a = a & 0x7F;      // clear bit 7
         }                       // don't do this
         
         if(((int)a % 2) == 1){  // if bit 0 is set
              a = a >> 1;
              a = a ^ 0x80;      // set bit 7
         }                          
    }
    Kurt

    BTW the test if ( a > 127 ) works only if a is defines as unsigned char.
    edit : removed xor-part my mistake
    Last edited by ZuK; 09-10-2005 at 03:17 PM.

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

    Thanks for your explanation. Why, however, would XOR not work ?

    I've tried compiling the code using your corrected code, but my encrypt / decrypt cycle still doesn't work.

    Also, my compiler is giving me an error, saying that "the comparison if(a > 127) will always be false due to limited range of data type." Using unsigned char, however, I can't seem to use "while(fin.get(a))" while reading in the file. Confused

    Thanks,
    Korhedron

  9. #9
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by Korhedron
    Also, my compiler is giving me an error, saying that "the comparison if(a > 127) will always be false due to limited range of data type."
    While you where writing I edited my post to point out that fact;
    You could change your code to
    Code:
    // bsl() - bitshift left. Code as follows.
    unsigned char bsl( unsigned char a ) {
         if(a > 127) {         // if bit 7 set
              a = a << 1;      // shift left 1 bit
              a = a ^ 0x01;    // set bit 0
         }                          
         else {         // if  bit 7 not set
              a = a << 1;      // shift left 1 bit
            //a = a & 0xFE;    // clear bit 7
         }                     // don't do that
        return a;
    }
    
    unsigned char bsr( unsigned char a  ) {
         if(((int)a % 2) == 0){  // if bit 0 not set
              a = a >> 1;        // shift right
            //a = a & 0x7F;      // clear bit 7
         }                       // don't do this
         else {  // if bit 0 is set
              a = a >> 1;
              a = a ^ 0x80;      //set bit 7
         }                          
         return a;
    }
    and use it this way
    Code:
         while(fin.get(a))
         {
              a = a ^ key[x++];
              if(strlen(key) == x) x = 0;
              
              a = bsl( a ); // the compiler will take care of converting to 
                             // unsigned char
              fout << a;
         }
    Kurt

    edit: removed the xor part. xor works as well.
    2.nd edit : replaced 2nd test with else.
    Last edited by ZuK; 09-10-2005 at 03:39 PM.

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

    I've tried as you said. Only, as before, the unsigned char a can't be used in fin.get(a)... I get this error :
    Code:
    30 encry.h no matching function for call to `std::basic_ifstream<char, std::char_traits<char> >::get(unsigned char&)'
    Basically, it seems the get function doesn't like unsigned chars...

  11. #11
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by Korhedron
    Basically, it seems the get function doesn't like unsigned chars...
    You need not change the type of the global variable a to unsigned char. Leave it as char. Only the shift functions need unsigned char as parameter and return type. Conversion will be done automagically.
    Kurt

  12. #12
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    I've also tried that, and I get, on the line "a = bsl(a);" the error "Void value not ignored as it ought to be"...
    Thanks for helping me out though I haven't coded in months, and as you can see, I've never been that good anyway !

    Korhedron.

  13. #13
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    That's another thing I have edited while you were writing. ( It's not my best day today ). It's ok now.
    Kurt

  14. #14
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Code:
    // bsl() - bitshift left. Code as follows.
    unsigned char bsl( unsigned char a ) {
         if(a > 127) {         // if bit 7 set
              a = a << 1;      // shift left 1 bit
              a = a ^ 0x01;    // set bit 0
         }                          
         else {         // if  bit 7 not set
              a = a << 1;      // shift left 1 bit
            //a = a & 0xFE;    // clear bit 7
         }                     // don't do that
        return a;
    }
    
    unsigned char bsr( unsigned char a  ) {
         if(((int)a % 2) == 0){  // if bit 0 not set
              a = a >> 1;        // shift right
            //a = a & 0x7F;      // clear bit 7
         }                       // don't do this
         else {  // if bit 0 is set
              a = a >> 1;
              a = a ^ 0x80;      //set bit 7
         }                          
         return a;
    }
    This is the latest version of the code.
    now it's tested and working.
    Kurt

  15. #15
    Confused
    Join Date
    Nov 2002
    Location
    Warwick, UK
    Posts
    209
    I've solved the problem My compiler was messing with signed chars instead of unsigned. I used this :

    Code:
    void bsl()
    {
         if(a.u > 127)
         {
              a.u = a.u << 1;
              a.u = a.u | 0x01;
         }
         
         else if(a.u < 128)
         {
              a.u = a.u << 1;
              a.u = a.u & 0xFE;
         }   
    }
    Same for bsr(). And I've made
    Code:
    union char_or_unsigned { char s; unsigned char u;} a;
    instead of signed / unsigned char. The encryptor function :
    Code:
    void encry(char* fileIN)
    {
         fin.open(fileIN, ios::binary);
         if(!fin) cout << "fin.ERROR";
         
         fout.open("temp.cry", ios::binary);
         if(!fout) cout << "fout.ERROR";
         
         while(fin.get(a.s))
         {
              a.s = a.s ^ key[x++];
              if(strlen(key) == x) x = 0;
              
              bsl();
              
              fout << a.s;
         }
         
         fin.close();
         fout.close();
    }
    The problem was in bsl and bsr : the two IFs were following. Only, sometimes the first IF would make the second true, and it would execute again. I simply needed to add "else" in front

    Thanks for all the help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. No clue how to make a code to solve problems!
    By ctnzn in forum C Programming
    Replies: 8
    Last Post: 10-16-2008, 02:59 AM
  2. C Pointers Problems
    By mhelal in forum C Programming
    Replies: 8
    Last Post: 01-10-2007, 06:35 AM
  3. String Manipulation problems -_-
    By Astra in forum C Programming
    Replies: 5
    Last Post: 12-13-2006, 05:48 PM
  4. contest problems on my site
    By DavidP in forum Contests Board
    Replies: 4
    Last Post: 01-10-2004, 09:19 PM
  5. DJGPP problems
    By stormswift in forum C Programming
    Replies: 2
    Last Post: 02-26-2002, 04:35 PM