Moving bits to alter characters

Pages: 12
Right I've got this encryptor program but I've just thought of a much better encryption method (edficency and safety wise for the program), the down side is Im not sureRight I've got this program working great now but I've just thought of a better encryption method (edficency and safety wise for the program), the down side is Im not sure how to do it although I am pretty certain people have done it before...

Is there any way I can read the whole string as binary and take the first bit and move it to the end instead? This would dramatically change the character it represents but it will remain within the 8bit (256) ASCII code im used to (rather than multiplying value by 3 and adding its position, this gets very unpredictable characters an is quite inefficient because it has todo this for every letter)
The short answer is not without some work. The processor literally does not deal with bits. It deals with bytes (or probably 4 or 8 bytes at a time, but either way, the byte is by definition the smallest lump of data it will work with).

You would have to take every byte, bitshift it one to the left, read the next byte and do some bit level fiddling to work out what the first bit is, OR mask that value with the one you just bitshifted, and then repeat for every byte, and with the final byte, OR mask it with the original first bit of the first byte. You cannot simply delete the first bit of the file and write it onto the end.
The other direction would be much simpler: read the last bit of a char, bitshift right, then add 128 to the result if the last bit was 1. The effect on the string should be similar as what you're planning.
c = (c >> 1) | ((c & 1) << CHAR_BIT)

should perform a rotate-right. Didn't test it though, and I do screw stuff like that up occasionally.
Last edited on
That's exactly what I meant, but coded much cooler than I would/could.

To analyze:
((c & 1) << CHAR_BIT) takes the last (lowest) bit and sets it as the highest (="add 128 if last bit was 1").
(c >> 1) shifts all bits right, thus dropping the lowest bit (which we still have).

The OR statement concatenates both "bitstrings", as no bit can be 1 in both "pieces".

In retrospect, the left-rotate variant isn't much more difficult if you know the amount of bits in your variable. I think this would do it:

(c << 1) | ((c & (1 << CHAR_BIT) >> CHAR_BIT)

Don't take my word for it though. Didn't test it.

(P.S.: Shouldn't the CHAR_BIT-count shifts be replaced with CHAR_BIT-1?)
@Gam

Yes, they should.
Ok i understand this but your all saying i need to know the length of my bytes, i automatically assume 8bit for ASCII code but is there a definate way to find out?
Most of the time, char is 8 bits. To be sure, you can use CHAR_BIT which is defined in <climits> (<limits.h> when you're C rather than C++).
I apologize because this is probably really simple to you but i'm not quite understanding how to write this code with correct syntax because i'm getting compile errors.

If i had a string called text for example that said "Hello" how would i edit this string by moving the bits to say "r╩╪╪▐"
(the whole string in binary, very 1st bit placed at end of string instead, then represented as characters again)

I would also need to reverse this to decrypt the string again so it's readable.
A char is a 1byte integer, interpreted by an ascii table (or something along those lines; the specifics don't matter). Bitshifts only work on integral types (not entirely sure why).

A string (C or C++ string) is a different story. It's not a number, and it has no integer representation. Instead, it's an array of chars/integral types.

To treat the string as a whole, you would need to glue the bitstrings of the separate chars together. This isn't so hard to perform (just shift the bits by BIT_CHAR*position and add/OR together), but it brings some serious issues with it:

The size of a string-chars-glued-together is 1byte*string-length. That means, if your string has more than 4 letters, an unsigned int is no longer sufficient. If it has more than 8, even a 64bit integer isn't sufficient. That's pretty much the limit.

It makes more sense to do it char-by-char. If you worry that it's too easy to decrypt, you can make it more advanced in other ways (e.g. first letter: shift-1, second letter: shift-2, etc.).
ok i understand, so would this work?

1
2
3
4
for(int i=0; i<text.size(); i++){
    text[i] = ((text[i] & 1) << CHAR_BIT);
    text[i] = (text[i] >> 1);
}


so this would take the right most bit for Each Char and set it as the left most bit?
And to undo is it just in reverse like this?

1
2
3
4
for(int i=0; i<text.size(); i++){
    text[i] = (text[i] << 1);
    text[i] = ((text[i] & 1) >> CHAR_BIT);
}
Erm, i tried using this code above and it did not work at all.
The first one left me with a load of SPaces and the second one crashed my program.

Please help!
No, there are some subtle differences between the right and left shift. Take a good look at hanst99's and my code snippets. It's not just the order. Try to work it out for yourself.

Also, I'm thinking it's (CHAR_BIT-1) that you need. Write it down on paper to be sure.
Well i would be happy to try and work it out so that i can learn better but i cant get the characters to change properly.

Hmm, maybe i would be able to make a function myself that finds the bit value and moves the bits down (just change the value to the same value as if all the bits have moved)
Last edited on
Okay now i really am confused, i made my own bit shift and got the same terrible result.

Here's the call to the function that i've made (i know there's better ways but oh well)...

1
2
3
4
for(int i=0; i<str.size(); i++){
str[i] = static_cast<char>(bitleft(str[i]));
ofile << str[i]; //write back to text document
}


Here's my actual bit shifter, (once again there is probably better ways)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int bitleft(char arg){
    int temp1 = static_cast<int>(arg);
    int temp2 = 0;
    
    if(temp1 >= 128){
        temp2 += 1;
        temp1 -= 128;}
    if(temp1 >= 64){
        temp2 += 128;
        temp1 -= 64;}
    if(temp1 >= 32){
        temp2 += 64;
        temp1 -= 32;}
    if(temp1 >= 16){
        temp2 += 32;
        temp1 -= 16;}
    if(temp1 >= 8){
        temp2 += 16;
        temp1 -= 8;}
    if(temp1 >= 4){
        temp2 += 8;
        temp1 -= 4;}
    if(temp1 >= 2){
        temp2 += 4;
        temp1 -= 2;}
    if(temp1 >= 1){
        temp2 += 2;
        temp1 -= 1;}
        
    return temp2;
}


However when i run the program to encrypt the text document everything just turns into lots of SP's
can anybody tell me why the character is not changing?
Last edited on
Well... yeah. Take a look at the ascii table. Half the stuff on there is "nonsense" output.

http://www.asciitable.com/
But a text documented is perfectly capable of storing full ascii code, and i know that the console program is also perfectly capable of using the full ascii code.
So what's going wrong??
My above code should turn each character into its number equivalent, from which i can workout it's bit-value and perform the bitshift.
My code technically doesn't do this but it should be a perfect equivalent for the output, which is then turned back into a character for the string.

However like I've said everything is just replaced with SPaces, please could somebody help me understand how to fix this!
If you want to use a text-printable encryption you need to make sure the characters are within the range of printable characters (min 0x20, max 0xFF) The only non-printable character in that range is I think 0x7F (it is sort of "printable" but instead of printing anything deletes the character to the left like you hit the backspace button). I did a simple binary encryption project many years ago for fun perhaps you can examine the concept and it will help you supply a solution to what you are doing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
namespace MyCrypt
{
  const char *DEFAULT_KEY = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=<>?,./\\|[]{}`~";
  const int eTable[] = {  85,170,-17, 68,153, 17,136, 34,-136, 51,-136, -51,-153, -51,-170 };
  const int dTable[] = { 136, 17,136,153,170,-85,-17,-68,  51,-34,  51,-170, -51,-153,-136 };
  const float chapters = 17.0;

  unsigned char cenc(const unsigned char cVal)
  {
    return (cVal + eTable[((int)ceil(cVal/chapters))-1]);
  }

  unsigned char cdec(const unsigned char cVal)
  {
    return (cVal + dTable[((int)ceil(cVal/chapters))-1]);
  }

  std::string encrypt(std::string s, std::string k = DEFAULT_KEY)
  {
    std::string sret;
    for(std::string::size_type i=0; i < s.size(); ++i)
    {
      unsigned char ci = s.at(i), ck = k.at(i % (k.size()-1));
      sret += (cenc(ci)^ck);
    }
    return sret;
  }

  std::string decrypt(std::string s, std::string k = DEFAULT_KEY)
  {
    std::string sret;
    for(std::string::size_type i=0; i < s.size(); ++i)
    {
      unsigned char ci = s.at(i), ck = k.at(i % (k.size()-1));
      sret += cdec(ci^ck);
    }
    return sret;
  }
};

I understand parts of this ok and it has given me a thought to a different encryption method, however i'm afraid i don't quite fully understand this because parts of the code appear to be in Java coding (i think), unfortunately it's quite off-putting as I found Java very difficult (crappy book) so i'm just gonna keep at C++ for now.

Please could you edit your code and maybe add a couple of comments to help me out here (i probably wont use this exact method but the more i understand it the more i can do with it)

Thanks @Texan
Pages: 12