1

显然这曾经适用于 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:“V”的未定义方法“^”:字符串

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

非常感谢

4

2 回答 2

4

在 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 数组。

于 2011-09-01T08:28:28.190 回答
1

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

所以你的例子应该调用:

text.length.times {|n| text[n] = (text[n].ord ^ key[n.modulo key.size].ord).chr }
于 2011-09-01T08:23:31.347 回答