Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's bad about shifting a 32-bit variable 32 bits?

I recently picked up a copy of Applied Cryptography by Bruce Schneier and it's been a good read. I now understand how several algorithms outlined in the book work, and I'd like to start implementing a few of them in C.

One thing that many of the algorithms have in common is dividing an x-bit key, into several smaller y-bit keys. For example, Blowfish's key, X, is 64-bits, but you are required to break it up into two 32-bit halves; Xl and Xr.

This is where I'm getting stuck. I'm fairly decent with C, but I'm not the strongest when it comes to bitwise operators and the like.

After some help on IRC, I managed to come up with these two macros:

#define splitup(a, b, c) {b = a >> 32; c = a & 0xffffffff; }
#define combine(a, b, c) {a = (c << 32) | a;}

Where a is 64 bits and b and c are 32 bits. However, the compiler warns me about the fact that I'm shifting a 32 bit variable by 32 bits.

My questions are these:

  • What's bad about shifting a 32-bit variable 32 bits? I'm guessing it's undefined, but these macros do seem to be working.
  • Also, would you suggest I go about this another way?

As I said, I'm fairly familiar with C, but bitwise operators and the like still give me a headache.

EDIT

I figured out that my combine macro wasn't actually combining two 32-bit variables, but simply ORing 0 by a, and getting a as a result.
So, on top of my previous questions, I still don't have a method of combining the two 32-bit variables to get a 64-bit one; a suggestion on how to do it would be appreciated.

like image 396
masseyc Avatar asked Apr 15 '10 20:04

masseyc


People also ask

What happens when you shift bits?

What Does Bit Shifting Mean? Bit shifting is an operation done on all the bits of a binary value in which they are moved by a determined number of places to either the left or right. Bit shifting is used when the operand is being used as a series of bits rather than as a whole.

Why would you want to shift bits?

Bit shifts help with optimization in low-level programming because they require fewer calculations for the CPU than conventional math. Bit shifting operations may be declared explicitly by the programmer, or automatically by the compiler if it can identify that such an optimization is possible.

What does shifting a bit mean?

Bitshifting shifts the binary representation of each pixel to the left or to the right by a pre-defined number of positions. Shifting a binary number by one bit is equivalent to multiplying (when shifting to the left) or dividing (when shifting to the right) the number by 2.

What does bit shifting do in C?

Left Shift and Right Shift Operators in C/C++ Takes two numbers, left shifts the bits of the first operand, the second operand decides the number of places to shift.


3 Answers

Yes, it is undefined behaviour.

ISO/IEC 9899:1999 6.5.7 Bitwise shift operators ¶3

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

C11 aka ISO/IEC 9899:2011 says the same.

You should first cast b to the target integer type. Another point is that you should put parentheses around the macro parameters to avoid surprises by operator precedences. Additionally, the comma operator is very useful here, allowing you to avoid the braces, so that the macro can be used as a normal command, closed with a semicolon.

#define splitup(a,b,c) ( (b) = (a) >> 32, (c) = (a) & 0xffffffff )
#define combine(a,b,c) ( (a) = ((unsigned long long)(b) << 32) | (c) )

Additional casts may be necessary for `splitup to silence warnings about precision loss by over-paranoid compilers.

#define splitup(a,b,c) ( (b) = (unsigned long)((a) >> 32), (c) = (unsigned long)((a) & 0xffffffff) )

And please don't even think about using your self-written encryption for production code.

like image 55
Secure Avatar answered Oct 19 '22 00:10

Secure


Shifting a 32-bit value by 32 bits or more is undefined in C and C++. One of the reasons it was left undefined is that on some hardware platforms the 32-bit shift instruction only takes into account 5 lowest bits of the supplied shift count. This means that whatever shift count you pass, it will be interpreted modulo 32. Attempting to shift by 32 on such platform will actually shift by 0, i.e. not shift at all.

The language authors did not want to burden the compilers written for such platform with the task of analyzing the shift count before doing the shift. Instead, the language specification says that the behavior is undefined. This means that if you want to get a 0 value from a 32-bit shift by 32 (or more), it is up to you to recognize the situation and process it accordingly.

like image 24
AnT Avatar answered Oct 19 '22 01:10

AnT


what's bad about shifting a 32-bit variable 32 bits?

Its better to assign 0 to n-bit integer than to shift it by n-bits.

Example:

 0 0 1 0 1 ----- 5 bit Integer  
 0 1 0 1 0 ----- 1st shift  
 1 0 1 0 0 ----- 2nd shift  
 0 1 0 0 0 ----- 3rd shift  
 1 0 0 0 0 ----- 4th shift  
 0 0 0 0 0 ----- 5th shift (all the bits are shifted!)  

I still don't have a method of combining the two 32-bit variables to get a 64-bit one

Consider: a is 64 bit, b and c are 32 bit

a = b;
a = a << 32; //Note: a is 64 bit
a = a | c;
like image 3
N 1.1 Avatar answered Oct 19 '22 00:10

N 1.1