ruby base64 编码/解码/解包 ('m' ) 麻烦

标签 ruby string base64 decode unpack

遇到一个奇怪的 ruby​​ 编码:

ruby-1.9.2-p180 :618 > s = "a8dnsjg8aiw8jq".ljust(16,'=')
 => "a8dnsjg8aiw8jq==" 
ruby-1.9.2-p180 :619 > s.size
 => 16 

ruby-1.9.2-p180 :620 > s.unpack('m0')
ArgumentError: invalid base64
    from (irb):631:in `unpack'

ruby-1.9.2-p180 :621 > s.unpack('m')
 => ["k\xC7g\xB28<j,<\x8E"] 
ruby-1.9.2-p180 :622 > s.unpack('m').first.size
 => 10

ruby-1.9.2-p180 :623 > s.unpack('m').pack('m')
 => "a8dnsjg8aiw8jg==\n" 
ruby-1.9.2-p180 :624 > s.unpack('m').pack('m') == s
 => false 

知道为什么这不是对称的!?为什么'm0'(decode64_strict)根本不起作用?输入字符串被填充为 base64 字母表中 4 个字符的倍数。这里是 14 x 6 位 = 84 位,即 10 1/2 8 位字节,即 11 字节。但是解码后的字符串似乎丢掉了最后一个字节?

我是否遗漏了一些明显的东西或者这是一个错误?解决方法? 比照。 http://www.ietf.org/rfc/rfc4648.txt

最佳答案

没有对称性,因为 Base64 不是填充字符串的一对一映射。让我们从实际解码的内容开始。如果您以十六进制查看解码后的字符串(使用例如 s.unpack('H*') 它将是这样的:

6B C7 67 | B2 38 3C | 6A 2C 3C | 8E

我将每个输入 block 的边界添加到 Base64 算法:它需要 3 个八位字节的输入并返回 4 个字符的输出。所以我们的最后一个 block 只包含一个输入八位字节,因此根据标准,结果将是 4 个以“==”结尾的字符。

让我们看看最后一个 block 的规范编码是什么。在二进制表示中 8E10001110。 RFC 告诉我们用零填充缺失的位,直到达到所需的 24 位:

100011 100000 000000 000000

我制作了 6 位组,因为这是我们从 Base64 字母表中获取相应字符所需要的。第一组 (100011) 转换为 35 位十进制,因此是 Base64 字母表中的 j。第二个 (100000) 是小数点后 32 位,因此是“g”。剩下的两个字符按照规则补成“==”。所以规范编码是

jg==

如果你现在看 jq==,在二进制中这将是

100011 101010 000000 000000

所以区别在于第二组。但是因为我们已经知道只有前 8 位是我们感兴趣的(“==”告诉我们 -> 我们只会从这四个字符中检索一个解码的八位位组)我们实际上只关心前两位第二组,因为第 1 组的 6 位和第 2 组的前 2 位构成了我们解码的八位位组。 100011 10 一起再次形成我们的初始 8E 字节值。其余 16 位与我们无关,因此可以丢弃。

这也暗示了为什么“严格”Base64 编码的概念有意义:非严格解码将丢弃末尾的任何垃圾,而严格解码将检查最后一组 6 中的剩余位是否为零。这就是为什么您的非规范编码会被严格的解码规则拒绝的原因。

关于ruby base64 编码/解码/解包 ('m' ) 麻烦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7063737/

相关文章:

c - 使用显式大小初始化 char 数组并初始化为大于该大小

java - 从 Java 执行 scanimage 命令

Ruby 转义 ARGV 参数或字符串作为 shell 命令的参数

ruby-on-rails - 如何在使用 Ruby on Rails ActiveSupport::Concern 功能时包含模块 "nest"?

mysql - Ruby 和 MySQL UTF-8 字符

string - Lua string.find 找不到一行中的最后一个单词

ruby-on-rails - 为 rails 中的特定 Controller 跳过/禁用 force_ssl

python - 简单 Python 代码中的 Str 对象错误

javascript - 无法从 req.header.authorization 解码 base64

android - 如何在android中使用base 64数据?