Simple XOR ruby 1.9.2

人盡茶涼 提交于 2019-12-24 07:05:32

问题


Apparently this used to work on ruby 1.8.7 but unfortunately not on 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

It returns

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

Any idea on how to get this working?

Thanks a lot


回答1:


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.




回答2:


Call #ord and #chr methods to convert from character to it's number representation and back to character

So your example should call:

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


来源:https://stackoverflow.com/questions/7267548/simple-xor-ruby-1-9-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!