Home > front end >  bash double parenthess substitution maximum size
bash double parenthess substitution maximum size

Time:09-22

I'm trying to compute an xor in bash, and the simplest way I have found so far is to use the $(( )) construct, like this:

$ printf '0x%X\n' $(( 0xA ^ 0xF ))
0x5

However, I need to xor two 128-bit numbers (32 hexadecimal characters) and it looks like the (( )) construct does not support such large numbers. Is there a way that (( )) can handle it?

$ printf '0x%X\n' $(( 0xA ^ 0xF ))
0x5
$ printf '0x%X\n' $(( 0xAA ^ 0xFF ))
0x55
$ printf '0x%X\n' $(( 0xAAA ^ 0xFFF ))
0x555
$ printf '0x%X\n' $(( 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ))
0x5555555555555555

There are only 16 5's instead of 32 as expected from the size of the input.

My input will be text strings without the 0x.

E.g.

x=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
y=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

printf '0x%X\n' $(( 0x$x ^ 0x$y ))

CodePudding user response:

Is there a way that (( )) can handle it?

No. You would have to patch Bash with some big-number support and recompile it yourself.

Use python.

$ python -c 'print("{:X}".format(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))'
55555555555555555555555555555555

CodePudding user response:

With Charles' advice, I have arrived at this (which is very similar to chrslg's answer):

printf '0x6X6X\n' $(( 0x${x:0:16} ^ 0x${y:0:16} )) $(( 0x${x:16} ^ 0x${y:16} ))

CodePudding user response:

Do it in two parts. Anyway, that the whole point of xor and hex, you could to it digit by digit if you wanted to. Here, since it is 32 digits numbers, and we have a 64 bits aka 16 hex digits precision arithmetics...

A=0123456789ABCDEF0123456789ABCDEF
B=ABCDEFABCDEF01234012345678956789

printf "0x" ; printf "6X" $((0x${A:0:16} ^ 0x${B:0:16})) $((0x${A:16:16} ^ 0x${B:16:16})) ; printf "\n"

=>

0xAAEEAACC4444CCCC41317131F13EAA66

(as it should)

CodePudding user response:

Bash can't handle such large numbers (though I don't have a reference for that).

Instead, you could offload to another language like Python, which has arbitrarily large integers:

x=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
y=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
python3 -c "print(format(0x$x ^ 0x$y, '#x'))"

Output:

0x55555555555555555555555555555555

Note: I'm assuming the inputs are trusted and only contain hex digits. If that's not guaranteed, this solution is totally unsecure since it doesn't sanitize anything. You could do the validation in Bash first with something like regex, or if you want to do it in Python, you could look at How do I access command line arguments? and Convert hex string to integer in Python.

  • Related