Простой XOR ruby ​​1.9.2 - PullRequest
       46

Простой XOR ruby ​​1.9.2

1 голос
/ 01 сентября 2011

Очевидно, что раньше он работал на ruby ​​1.8.7, но, к сожалению, не на 1.9.2

class String
  def xor(key)
    text = dup
    text.length.times {|n| text[n] ^= key[n.modulo key.size] }
    text
  end
end

def encode(_original, _pass = 'testvendor')
  _original.xor(_pass)
end

puts encode('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.')

#output=>    
8
EE
DEBDREBDEVSR
TTTT
TNZV0D
SE E    CRVSETENR   D

TT
    EKS0DSO VD
EVVTE S 
RSREXE+E T
 RR
T _TOEDE RO E
TTD
K

Возвращает

NoMethodError: undefined method `^' for "V":String

Есть идеи, как заставить это работать?

Большое спасибо

Ответы [ 2 ]

4 голосов
/ 01 сентября 2011

В версии 1.8 метод String#[] возвратил Fixnum, который был байтом указанного индекса. В более новой версии String#[] возвращает строку, поскольку строки состоят из символов, а сопоставление символов в байтах зависит от кодировки. Похоже, вы используете строку в качестве байтового буфера, поэтому вы должны работать в массиве вместо строки:

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

А затем использовать его:

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

Тогда, если вам действительно нужна строка (которая будет содержать набор непечатаемых управляющих символов и ноль байтов и тому подобное), тогда:

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

А потом распаковать:

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

Все это должно поддерживать UTF-8 на всем пути, и это то, что вы хотите.

Возможно, вы могли бы пропатчить свой xor в Enumerable и пропустить бизнес to_a, если хотите. Вы также можете адаптировать это для патча для String.

Вам больше не следует использовать String для байтовых буферов, для этого лучше использовать массивы Fixnum с явной обработкой кодировки.

1 голос
/ 01 сентября 2011

Вызовите #ord и #chr методы для преобразования из символа в его представление числа и обратно в символ

Итак, ваш пример должен вызвать:

text.length.times {|n| text[n] = (text[n].ord ^ key[n.modulo key.size].ord).chr }
...