命令:
echo "HelloWorld==" | base64 -d | base64
输出:
HelloWorlQ==
为什么我d
现在是a Q
?
编辑:
我不想从任意数据开始并对其进行 Base64 编码。我的目的是从 Base64 开始并以 Base64 结束,在此期间只生成一个二进制值。
编辑2:
我注意到,如果输入字符串是四个字符的倍数,则不会发生这种情况,所以我认为这是与填充的交互:
❯ echo 'abcdefghij==' | base64 -d | base64
abcdefghig==
❯ echo 'abcdefgh' | base64 -d | base64
abcdefgh
编辑3
删除了令人困惑的标志提及-i
,事实证明这与我的问题无关。
答案1
HelloWorld==
包含无法解码的信息,并且在技术上不是有效的 Base64,因为它们通常应该被0
填充。当您使用 . 时,其中包含的额外1
s 将被忽略并丢失echo "HelloWorld==" | base64 -d
。
解释...
Base64 适用于 4 个字符的组。每个字符代表 6 位,因此每组 4 个解码为 3 个字节(每个字节 8 位)。唯一的例外是最后 4 个字符,该字符会根据符号的数量而变化=
。 Base64 字符串始终能被 4 整除。
- 0 解码为 3 字节
- 1 = 解码为 2 字节
- 2 == 解码为 1 字节
在你的例子中Hell
和oWor
都是有效的。但ld==
事实并非如此。要了解原因,请参阅此查找表: https://en.wikipedia.org/wiki/Base64
ld==
应该只解码为一个字节,因为它=
末尾有两个字节。但ld
解码为: 100101 011101
。一个字节只有八个8位。因此,当您使用 解码字符串时base64 -d
,只会100101 01
将其转换为字节,并且末尾1101
将被完全忽略。
任何以 结尾的 Base 64 字符串==
必须仅使用最后一个字符的前两位。这是唯一有效的结尾==
是Q==
A==
w==
g==
答案2
是的,这是与填充的交互。
让我们通过解码来查看您的实际编码数据,并且(因为它不是 ASCII 字符串)将其转换为二进制:
$ base64 -d <<<'HelloWorld==' | xxd -b
00000000: 00011101 11101001 01100101 10100001 01101010 00101011 ..e.j+
00000006: 10010101 .
HelloWorld==
这是经过 Base64 编码的数据。菲利普·库林解释了最后部分解码的复杂性,并且在某种程度上,在解码数据时实际上ld==
仅使用了由 编码的数据的三分之一。d
下面我将展示Q
重新编码数据时的来源。
让我们重复一下这个二进制文件:
00011101 11101001 01100101 10100001 01101010 00101011 10010101
以六位为一组(这是 Base64 编码器将使用的):
000111 011110 100101 100101 101000 010110 101000 101011 100101 01
最后用四个零位填充以形成 10 个完整的 6 位代码:
000111 011110 100101 100101 101000 010110 101000 101011 100101 010000
这010000
是Q
您重新编码数据时看到的(请参阅Base64 代码表)。
答案3
管道不整齐。您应该先编码,然后再解码。
$ echo "Hello World!==" | base64 | base64 -id
Hello World!==
您正在解码无效的 Base64 编码格式。