Question

I am trying to do bitwise xor 2 ASCII strings of the same length in ruby. I have come to the following:

'A'.unpack('B*').zip('B'.unpack('B*')).map{|a, b| (a.to_i ^ b.to_i).to_s}.pack('b*')
 => "\003"

It works. However, when performing string of 2 or more chars, it behaves wierdly, i think because of the value is too big for Fixnum, see below:

'AA'.unpack('B*').zip('BB'.unpack('B*')).map{|a, b| (a.to_i ^ b.to_i).to_s}.pack('b*')
 => "_\003"

If I stop right after the xor, without the to_s part, I see that it is not doing the bitwise XOR correctly:

'AA'.unpack('B*').zip('BB'.unpack('B*')).map{|a, b| (a.to_i ^ b.to_i)}
 => [1515925259] 

Can someone help? Or can someone suggest another way of doing this? Many thanks

Was it helpful?

Solution

I think you want to unpack with C (8-bit unsigned) rather than B (bit string) since the xor operator ^ operates on numbers rather than strings:

'AA'.unpack('C*').zip('BB'.unpack('C*')).map { |a,b| a^b }.pack('C*')
# => "\x03\x03"

3 is what one would expect from xoring 65 ('A') with 66 ('B').

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top