简单的XOR红宝石1.9.2

问题描述 投票:1回答: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

关于如何使这个工作的任何想法?

非常感谢

ruby bit-manipulation xor ruby-1.9.2
2个回答
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
投票

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

所以你的例子应该调用:

text.length.times {|n| text[n] = (text[n].ord ^ key[n.modulo key.size].ord).chr }
© www.soinside.com 2019 - 2024. All rights reserved.