尝试对 zlib 压缩字符串进行反向异或会导致 header 错误

Trying to reverse XOR on a zlib compressed string causes header error

对于本次任务中出现的乱七八糟的字符,我们深表歉意。在我的脚本中,我像这样压缩和异或数据

buff2 = Deflate.deflate(buff)
buff3 = ''

buff2.each_char do |c|
  buff3 << (c.chr.ord ^ 0xFF)
end

解压后的字符串是这样的

x��=�0 @�=��<38�k7l�v�Х?H�!��rwZ����p ��8#��;�ZDS)}0�b��J�s�qz>����� ĿD��+"���]��I8dS2����ۿ�e_���~���

异或后

câ4Âñ=Ïó¿ÂXwÃÌÇNÈw/ZÀ·sÞñhW¥YHCßöÇÜ{jÄ¥»¬àÖÏz} Áé@rùß;@»^+ÔåÝùrR¢V~¶Ç¬ÍD0 $@Y ^FâW

然而,当我尝试反转 XOR(以相同的方式)时,字符串看起来确实相似,但它缺少 � 那个字符串看起来像这样

²xË=Â0 @á=§<38±k7lvèÐ¥?H!¨rwZ¦·¼ïp îþ8#;åZDS)}0 bÉJÆsqz>¿ëíæ Ä¿D¡Ô+"ú­]©I8dS2»ä°ÏóÛ¿¦e_¡¹æ~àè¨

我尝试用 zlib 对其进行膨胀,但失败了 incorrect header check (Zlib::DataError)

我要如何将 �s 更改为实际字符串?

通过 '' 创建字符串时,其 encoding defaults to UTF-8: (or more precisely your script encoding)

buff3 = ''
buff3.encoding
#=> #<Encoding:UTF-8>

这使得 << 将值解释为 Unicode 代码点(可能导致多个字节)

str = ''
str << 200       #=> "È"
str.codepoints   #=> [200]
str.bytes        #=> [195, 136]

如果你想处理字节,你应该使用二进制编码,例如通过 String#b or String::new:

str = ''.b
str.encoding
#=> #<Encoding:ASCII-8BIT>

str = String.new
str.encoding
#=> #<Encoding:ASCII-8BIT>

在二进制编码字符串中,代码点等于字节:(并且 non-ASCII 字节呈现为 \xnn

str = String.new
str << 200       #=> "\xC8"
str.codepoints   #=> [200]
str.bytes        #=> [200]

此外,您可以使用 byte-based each_byte 方法,该方法恰好适用于 return 数值:(因此您不必通过 ord)

buff2.each_byte do |b|
  buff3 << (b ^ 0xFF)
end

或者,您可以使用 pack and unpack:

str = 'foobar'

enc = str.unpack('C*').map { |b| b ^ 0xff }.pack('C*')
#=> "\x99\x90\x90\x9D\x9E\x8D"

dec = enc.unpack('C*').map { |b| b ^ 0xff }.pack('C*')
#=> "foobar"

C 表示“8 位无符号”,* 表示多次出现。

如果你只是想翻转位,还有Integer#~:

[102].map { |b| b ^ 0xff } #=> [153]
[102].map { |b| ~b }       #=> [153]
[102].map(&:~)             #=> [153]