为什么base64编码的字符串末尾有=符号


320

我知道什么是base64编码以及如何base64在C#中计算编码,但是我多次看到,当我将字符串转换为base64时,最后会有一个=

提出了一些问题:

  1. 难道一个base64字符串总是以结束=
  2. 为什么=在末尾附加get?

9
这与C#完全无关。
BoltClock

19
实际上,它与c#有关,并非所有语言都包含=,例如许多perl库都省略了=,因此了解用户使用的环境实际上是相关的。
2014年

似乎这样会使它在某些情况下变得不太有效,因为它很容易被发现。
dgo

6
@ user1167442 Base64不能用于混淆。它用于将二进制数据(或具有unicode和其他特殊字符的字符串)作为字符串传输。
NH。

Answers:


268

它用作填充

一个更完整的答案是,base64编码的字符串并不总是以a =结尾,=如果需要将字符串填充到适当的长度,它只会以一或两个结尾。


3
“需要填充字符的一种情况是串联多个Base64编码的文件。”
安德烈·佩尔(AndréPuel)2014年

1
@AndréPuel:重新同步一个=就足够了。如果您想找到边界,则应始终存在一个终止符(并且仍然只需要一个字符)。Base64的整个填充概念只是个脑子……
6502

5
但是,该链接与base64完全无关。
NH。

1
我只希望发布一个相关且可靠的链接,并base64通过插图和示例有效地解释填充。Wikipedia的当前链接与@NH完全无关。提到。
Fr0zenFyr

1
@ Fr0zenFyr如果您想要一个链接,则en.wikipedia.org/wiki/Base64#Output_padding非常好。但是Badr答案确实是一个更好的答案(它尚未获得选票)。
NH。

311

1-不

2-简短的回答:第65个字符(“ =符号”)仅在消息编码的最终过程中用作补充。

如果您的字符串具有3个字符的倍数,则不会有'='符号,因为Base64编码使用每个三个字节(8位)并将它们表示为ASCII标准中的四个可打印字符。

细节 :

(a)如果要编码

ABCDEFG <=> [ ABC] [ DEF] [G

Base64将处理(产生4个字符)第一个块和第二个块(因为它们完成了),但是对于第三个块,它将==在输出中添加一个双精度 字以完成所需的4个字符。因此,结果将是 QUJD REVG Rw == (无空格)

(b)如果您想编码...

ABCDEFGH <=> [ ABC] [ DEF] [GH

同样,它将=在输出的末尾仅添加一个以获取4个字符,结果将为 QUJD REVG R0g = (无空格)


26
这比其他答案甚至Wikipedia更为完整和清晰,并且应该比已接受的答案拥有更多的选票,后者仅指向Wikipedia链接。恭喜您!已投票!
ANewGuyInTown

2
@ANewGuyInTown接受的解决方案中的Wikipedia链接不正确,它与base64上的填充无关。Legolas在下面回答中链接了正确的页面
Fr0zenFyr


66

维基百科

最后的'=='序列指示最后一组仅包含一个字节,而'='指示其包含两个字节。

因此,这是某种填充。


16
  1. 没有。
  2. 将Base64编码的字符串的长度填充为4个字符的倍数,以便可以正确对其进行解码。

3
我最后删除了=,并测试了100万个字符串。解码始终匹配。
vivek_23 '19


11

等号(=)用作base64编码的某些形式的填充。有关base64 的维基百科文章提供了所有详细信息。


2
您能否解释为什么“ ==”是1个字节而“ =“ =”是2个字节的逻辑?我就是听不懂。怎么输入:“任何肉体的快乐”。可以得到结果“ YW55IGNhcm5hbCBwbGVhc3VyZS4 =“,而“任何狂欢”可以得到结果“ YW55IGNhcm5hbCBwbGVhc3VyZQ ==”?
2013年

14
并非'=='是1个字节,'='是2个字节。在这种情况下,您需要在整个字符串中始终使用4字节的倍数。因此,您用'='符号填充,直到得到为止。第一个字符串比第二个字符串多一个字符,因此需要较少的填充'='。
Sam Holloway 2013年

2
这个答案应该是评论吗?
Fr0zenFyr

9

它是填充。从http://en.wikipedia.org/wiki/Base64

从理论上讲,不需要填充字符,因为可以从Base64位数计算出丢失的字节数。在某些实现中,填充字符是强制性的,而对于其他实现则不使用。需要填充字符的一种情况是串联多个Base64编码的文件。


1
关于“需要填充字符的一种情况是串联多个Base64编码的文件”部分。是错的。例如,当连接两个base64文件时,每个文件的源字节为3个字节长,base64字符串将为4个字符长,并且没有填充字节。当您将这两个base64字符串连接在一起时,将无法基于连接的字符串来判断一个在哪里开始,一个在哪里停止。因此,依靠base64填充来解决此问题是行不通的。这个问题将存在与字节长度的任何文件被3整除
罗恩ç

1
我想这意味着最终结果应该是输入的串联的情况。例如,decode(encode(A)+encode(B))=A+B可以使用填充,但不能不使用。
托马斯·伦纳德

也许但是这种有限的使用不允许在将编码字符串串联在一起的一般情况下依赖于填充字符。我仅提及它是为了帮助可能认为他们可以使用它的开发人员。
罗恩C

1
我认为您的反对意见确实突出了填充和定界概念之间的区别。通常不希望串联的结果包含足够的信息以使其可逆。您不会知道“ c3dpenpsZXJz”最初是“ c3dpenps” +“ ZXJz”还是“ c3dp” +“ enpsZXJz”。但是您也不知道“ swizzlers”最初是“ swi” +“ zzlers”还是“ swizzl” +“ ers”。
GargantuChet

1
从相关的Base64填充答案中复制我的评论:> Base64并置[使用'='填充]允许编码器并行处理大块,而无需将块大小对齐为三的倍数。类似地,作为一种实现细节,可能存在一个编码器,该编码器需要刷新内部数据缓冲区,其大小不是三的倍数。
安德烈·D

7

http://www.hcidata.info/base64.htm

将“ Mary had”编码为Base 64

在此示例中,我们使用一个简单的文本字符串(“ Mary had”),但是无论数据是什么(例如图形文件),该原理都适用。为了将每24位输入数据转换为32位输出,Base 64编码将24位拆分为4个6位的块。我们注意到的第一个问题是“ Mary have”不是3字节的倍数-它是8字节长。因此,最后一组位只有4位长。为了解决这个问题,我们添加了两个额外的位“ 0”,并在末尾添加“ =”来记住这一事实。如果要转换为Base 64的文本字符串长7个字节,则最后一组将具有2位。在这种情况下,我们将添加四个额外的位“ 0”,并通过在最后放置“ ==”来记住这一事实。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.