简单的XOR红宝石1.9.2

时间:2011-09-01 08:06:35

标签: ruby bit-manipulation xor ruby-1.9.2

显然这曾经用于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 个答案:

答案 0 :(得分:4)

在1.8中,String#[]方法返回了一个Fixnum,它是指定索引处的字节。在较新的版本中,String#[]返回一个String,因为字符串由字符组成,字符到字节的映射取决于编码。看起来你正在使用String作为字节缓冲区,所以你应该使用Array而不是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)

然后,如果你真的想要一个String(它包含一堆不可打印的控制字符和零字节等等),那么:

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 :(得分:1)

调用#ord#chr方法将字符转换为数字表示并返回字符

所以你的例子应该叫:

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