将nginx uuid从十六进制转换为Base64:如何涉及字节顺序?

时间:2015-12-05 16:32:18

标签: ruby nginx binary endianness nibble

可以将Nginx配置为生成uuid suitable for client identification。在收到来自新客户端的请求后,它会在将请求上游转发到源服务器之前以两种形式附加一个uuid:

  • 在Base64中使用uuid的Cookie(例如CgIGR1ZfUkeEXQ2YAwMZAg==
  • 标头,带有十六进制的uuid(例如4706020A47525F56980D5D8402190303

我想将十六进制表示转换为Base64等价物。我有一个Ruby的工作解决方案,但我没有完全掌握底层的机制,尤其是字节顺序的切换:

hex_str = "4706020A47525F56980D5D8402190303"

hex_str作为一系列高半字节(最重要的4位优先)二进制数据处理,生成(ASCII编码)字符串表示:

binary_seq = [hex_str].pack("H*")

# 47 (71 decimal) -> "G"
# 06  (6 decimal) -> "\x06" (non-printable)
# 02  (2 decimal) -> "\x02" (non-printable)
# 0A (10 decimal) -> "\n"
# ...

#=> "G\x06\x02\nGR_V\x98\r]\x84\x02\x19\x03\x03"

binary_seq映射到32位 little-endian 无符号整数的数组。每4个字符(4个字节= 32位)映射到一个整数:

data = binary_seq.unpack("VVVV")

# "G\x06\x02\n"      ->  167904839 (?)
# "GR_V"             -> 1449087559 (?)
# "\x98\r]\x84"      -> 2220690840 (?)
# "\x02\x19\x03\x03" ->   50534658 (?)

#=> [167904839, 1449087559, 2220690840, 50534658]

data视为32位 big-endian 无符号整数的数组,生成(ASCII编码)字符串表示形式:

network_seq = data.pack("NNNN")

#  167904839 -> "\n\x02\x06G"      (?)
# 1449087559 -> "V_RG"             (?)
# 2220690840 -> "\x84]\r\x98"      (?)
#   50534658 -> "\x03\x03\x19\x02" (?)

#=> "\n\x02\x06GV_RG\x84]\r\x98\x03\x03\x19\x02"

在Base64字符串中编码network_seq

Base64.encode64(network_seq).strip

#=> "CgIGR1ZfUkeEXQ2YAwMZAg=="

我粗略地理解,big-endian是网络通信的标准字节顺序,而little-endian在主机上更常见。为什么nginx提供了两种需要切换字节顺序来转换的形式,我不确定。

我也不了解.unpack("VVVV").pack("NNNN")步骤的工作原理。我可以看到G\x06\x02\n变为\n\x02\x06G,但我不明白到达那里的步骤。例如,关注hex_str的前8位数,为什么.pack(H*).unpack("VVVV")会产生:

"4706020A" -> "G\x06\x02\n" -> 167904839

而直接转换为base-10会产生:

"4706020A".to_i(16) -> 1191576074

?我问这个事实表明我需要澄清所有这些转换中到底发生了什么:)

0 个答案:

没有答案