Ruby Byte XOR странный результат - помогите пожалуйста

Я выполнял XOR данных, и с моим шестнадцатеричным XOR все шло хорошо. Было рекомендовано использовать байтовое XOR (^) и работать только с байтами. Я думал, что это не займет много времени, чтобы изменить это, но у меня есть какое-то странное поведение, которого я не ожидал.


Не могли бы некоторые добавить немного света относительно того, почему я получаю другой результат, если я обрабатываю строку как байты. Я ожидал, что будет то же самое.

 m_hex_string ="124f33e6a118566377f237075354541f0a5a1b"
 m_XOR_string ="662756c6c27732065796586974207468652870"
 m_expected ="the code don't work"
 m_expected_hex ="74686520636f646520646f6e277420776f726b"

def XOR_hex_strings(a,b)
  (a.hex ^ b.hex).to_s(16)
end

def XOR_byte_strings(s1,s2) 
   xored = s1.bytes.zip(s2.bytes).map { |(a,b)| a ^ b }.pack('c*')
end

def hex_digest(hexdigest)
   [hexdigest].pack("H*")
end

   puts "My strings for stack overflow"
   puts "'"+hex_digest(XOR_hex_strings(m_hex_string,m_XOR_string))+"'"
   puts "'"+hex_digest(XOR_byte_strings(m_hex_string,m_XOR_string))+"'"

Полученные результаты:

 My strings for stack overflow
 'the code don't work'
 'tje`#ode ?on't ~mrk'

Текст должен быть одинаковым «код не работает» для обоих методов. Я действительно хотел бы знать, почему, а не просто правильный фрагмент кода. Спасибо.


person Darren Rogan    schedule 08.05.2013    source источник
comment
Дайте угадаю: тот, кто предложил .bytes, не знал, что ваши строки были шестнадцатеричными.   -  person John Dvorak    schedule 08.05.2013
comment
правда, и теперь вы сказали это. моя ошибка довольно очевидна, поскольку байты работают только со строками, а не с шестнадцатеричными строками.   -  person Darren Rogan    schedule 08.05.2013
comment
XOR_byte_strings([m_hex_string].pack('H*'),[m_XOR_string].pack('H*'))   -  person Darren Rogan    schedule 08.05.2013
comment
Это ответ или уточнение к вопросу? Если это ответ, вы должны опубликовать его как таковой (с пояснениями и т.п., если возможно)   -  person John Dvorak    schedule 08.05.2013
comment
Я не мог опубликовать ответ на свой вопрос в течение 6 часов. Это было преобразование шестнадцатеричной строки в строку с использованием пакета. Ответ ниже более четко отвечает на него. Спасибо   -  person Darren Rogan    schedule 08.05.2013


Ответы (1)


Как уже говорилось в комментариях, bytes не учитывает шестнадцатеричный формат, он просто возвращает целые значения для "1", "2", "4", "f" и т. д. Вы можете преобразовать шестнадцатеричную строку с помощью pack:

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

unpack преобразует это в массив байтов, как < a href="http://ruby-doc.org/core-2.0/String.html#method-i-bytes" rel="nofollow">bytes, но более явный и быстрый (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]

Окончательный метод будет выглядеть так:

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

Если скорость является проблемой, взгляните на гем fast_xor:

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
person Stefan    schedule 08.05.2013