Xor of String in Ruby

Ruby bitwise xor 2 same length ascii string

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').

how to do the XOR operation between two hexa strings?

That would work for any base:

>> (a.to_i(16) ^ b.to_i(16)).to_s(16) 
=> "f51c527949bb4dca36d0afae2c39e2f"

But you can use String#hex for hexadecimal strings.

Ruby Byte XOR strange result - help please

As already said in the comments, bytes doesn't take the hex format into account, it just returns the integer values for "1", "2", "4", "f" etc. You can convert the hex string with pack:

[m_hex_string].pack("H*")
# => "\x12O3\xE6\xA1\x18Vcw\xF27\aSTT\x1F\nZ\e"

unpack converts this into a byte array, just like bytes but more explicit and faster (IIRC):

[m_hex_string].pack("H*").unpack("C*")
# => [18, 79, 51, 230, 161, 24, 86, 99, 119, 242, 55, 7, 83, 84, 84, 31, 10, 90, 27]

The final method would look like:

def XOR_pack_unpack_strings(s1, s2)
s1_bytes = [s1].pack("H*").unpack("C*")
s2_bytes = [s2].pack("H*").unpack("C*")
s1_bytes.zip(s2_bytes).map { |a, b| a ^ b }.pack('C*')
end

If speed is an issue, take a look at the fast_xor gem:

require 'xor'

def XOR_fast_xor_strings(s1_hex, s2_hex)
s1 = [s1_hex].pack("H*")
s2 = [s2_hex].pack("H*")
s1.xor!(s2)
end

Looking for better logical XOR solution with strings

Enumerable actually defines a one? method which does exactly what you need.

# So either...

[a, b, c].one?(&:present?)

# or

[a, b, c].one?(&:presence)

# ... would do the trick in this case.

Unfortunately if you want two? or etcera, you're out of luck.

Ruby XOR bit wise manipulation cryptography exercise

In your to_hex_array method you shouldn't be converting the bytes to strings (your call to to_s 16) - that's why you end up trying to xor strings rather than integers

That does mean that your xor method will need an extra step to turn the result from an array of integers to a string - something like

array_of_integers.map {|int| int.to_s(16)}.join

Simple XOR ruby 1.9.2

In 1.8, the String#[] method returned a Fixnum which was the byte at the specified index. In newer version, String#[] returns a String because strings are made of characters and the character-to-byte mapping depends on the encoding. Looks like you're using a String as a byte buffer so you should be working in Array instead of String:

class Array
def xor(key)
a = dup
a.length.times { |n| a[n] ^= key[n % key.size] }
a
end
end

And then to use it:

mangled_array = string.codepoints.to_a.xor(key.codepoints.to_a)

Then if you really want a String (which will contain a bunch of unprintable control characters and zero bytes and such things), then:

mangled_string = mangled_array.inject('') { |s,c| s << c }

And then to unpack:

mangled_string.
codepoints.
to_a.
xor(key.codepoints.to_a).
inject('') { |s,c| s << c }

All of this should maintain UTF-8 all the way through and that's what you want.

You could probably patch your xor into Enumerable and skip the to_a business if desired. You could probably also adapt this to patch for String as well.

You shouldn't be using String for byte buffers anymore, you're better off using arrays of Fixnum for that with explicit encoding handling.



Related Topics



Leave a reply



Submit