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
Rails on Windows - Install Issue
How to Dynamically Alter Inheritance in Ruby
Add "# Coding: Utf-8" to All Files
How to Iterate Activerecord Attributes, Including Attr_Accessor Methods
How to Capture Values in Command Line and Add to Recipe
What's the Difference Between Colon ":" and Fat Arrow "=>"
Return Index of All Occurrences of a Character in a String in Ruby
Problems Installing Ruby on Mountain Lion - Ruby 1.9.3 Wont' Compile
Rails Gem Rails3-Jquery-Autocomplete How to Scope by User
Ruby 1.9 + Sinatra Incompatible Character Encodings: Ascii-8Bit and Utf-8
Does Ruby Provide a Way to Do File.Read() with Specified Encoding
Keep Form Fields Filled After an Error (Ror)
Has_Many :Through with Counter_Cache
In 'Require': No Such File to Load -- Iconv (Loaderror)
Double-Splat Operator Destructively Modifies Hash - Is This a Ruby Bug