开发者

Simple XOR ruby 1.9.2

开发者 https://www.devze.com 2023-04-01 00:36 出处:网络
Apparently this used to wor开发者_StackOverflow中文版k on ruby 1.8.7 but unfortunately not on 1.9.2

Apparently this used to wor开发者_StackOverflow中文版k 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


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.


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 }
0

精彩评论

暂无评论...
验证码 换一张
取 消