2

I am trying to understand how to perform bit shift operations in Python. Coming from C#, it doesn't work in the same way.

The C# code is;

var plain=0xabcdef0000000; // plaintext
var key=0xf0f0f0f0f123456; // encryption key

var L = plain;
var R = plain>>32;

The output is;

000abcdef0000000 00000000000abcde

What is the equivilent in Python? I have tried;

plain = 0xabcdef0000000
key = 0xf0f0f0f0f123456

print plain

left  = plain
right = plain >> 32

print hex(left)
print hex(right)

However, it doesn't work. The output is different in Python. The 0's padding are missing. Any help would be appreciated!

5
  • 2
    what exactly means "it doesn't work"? Commented Nov 25, 2014 at 13:32
  • 1
    I didn't get the same output with the Python version. The padded 0's are missing. Commented Nov 25, 2014 at 13:40
  • but you know that 0x00000000000abcde == 0xabcde, right? Anyway, for printing, string formatting will do the trick. Commented Nov 25, 2014 at 13:43
  • Yes, but 0xabcdef != 0xabcde Commented Nov 25, 2014 at 13:46
  • @TomSothcott: where in your C# code do you see 0x0000000000abcdef then? Shifting 0xabcdef0000000 32 bits to the right still resulted in 0x00000000abcde being printed, because that's the 64-bit value produced. The last 8 bits were shifted off. Commented Nov 25, 2014 at 13:49

3 Answers 3

3

The hex() function does not pad numbers with leading zeros, because Python integers are unbounded. C# integers have a fixed size (64 bits in this case), so have an upper bound and can therefor be padded out. This doesn't mean those extra padding zeros carry any meaning; the integer value is the same.

You'll have to explicitly add those zeros, using the format() function to produce the output:

print format(left, '#018x')
print format(right, '#018x')

The # tells format() to include the 0x prefix, and the leading 0 before the field width asks format() to pad the output:

>>> print format(left, '#018x')
0x000abcdef0000000
>>> print format(right, '#018x')
0x0000000000abcde

Note that the width includes the 0x prefix; there are 16 hex digits in that output, representing 64 bits of data.

If you wanted to use a dynamic width based on the number of characters used in key, then calculate that from int.bit_length(); every 4 bits produce a hex character:

format(right, '#0{}x'.format((key.bit_length() + 3) // 4 + 2))

Demo:

>>> (key.bit_length() + 3) // 4 + 2
17
>>> print format(right, '#0{}x'.format((key.bit_length() + 3) // 4 + 2))
0x0000000000abcde

But note that even the key is only 60 bits in length and C# would pad that value with an 0 as well.

Sign up to request clarification or add additional context in comments.

Comments

1

I have no problem with you you tried

>>> hex(0xabcdef0000000)
'0xabcdef0000000'

>>> hex(0xabcdef0000000 >> 32)
'0xabcde'

Comments

1
In [83]: plain=0xabcdef0000000    

In [84]: plain>>32
Out[84]: 703710

In [85]: plain
Out[85]: 3022415462400000

In [87]: hex(plain)
Out[87]: '0xabcdef0000000'

if

In [134]: left  = plain
In [135]: right = plain >> 32

Then

In [140]: '{:0x}'.format(left)
Out[140]: 'abcdef0000000'

In [143]: '{:018x}'.format(right)
Out[143]: '0000000000000abcde'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.