base 64编码用于什么?


Answers:


939

当您有一些要通过网络传送的二进制数据时,通常不会仅通过以原始格式通过流传输位和字节来做到这一点。为什么?因为某些媒体是用于流文本的。您永远都不知道-有些协议可能会将二进制数据解释为控制字符(例如调制解调器),或者您的二进制数据可能被搞砸了,因为基础协议可能会认为您输入了特殊的字符组合(例如FTP如何转换行)结局)。

因此,为了解决这个问题,人们将二进制数据编码为字符。Base64是这些编码类型之一。

为什么是64?
因为您通常可以依赖于许多字符集中存在的相同64个字符,并且可以合理地确信数据将最终完好无损地连接到另一端。


104
(从理论上讲,您可以进行base-80编码或类似的编码,但是难度会大大增加。二进制的
Jon Skeet

13
@yokees:不能保证,它们只是几乎总是安全的字符。这就是为什么Base-64(en.wikipedia.org/wiki/Base-64)有多种形式的原因。

8
这是否意味着所有网络类型的数据传递都应使用某种编码?
Tanner Summers

6
但是,为什么使用base64方法对字符串数据进行编码?例如在javascript atob函数中,这是否意味着服务器将json文件编码为base64格式?特殊字符可能是一个用例,但为什么不使用utf8,它们是否相等?对此,任何其他资源将不胜感激。
partizanos

4
如果有人知道的话,至少列出一些会失败的协议会很不错。
塔德吉

202

基本上,这是在ASCII文本中编码任意二进制数据的一种方式。每3个字节的数据需要4个字符,最后可能还要填充一点。

基本上,输入的每6位均以64个字符的字母编码。“标准”字母使用AZ,az,0-9和+和/,并带有=作为填充字符。有网址安全变体。

Wikipedia是更多信息的相当不错的来源。


在像php这样的语言中,二进制数据是从那里来的。我们几乎总是处理字符串数据,即文本。
Cholthi Paul Ttiopic'9

3
@CholthiPaulTtiopic:加密或压缩或声音/图像/视频的结果。
乔恩·斯基特

1
@CholthiPaulTtiopic:恐怕我不知道您所说的“关于存储的含义”是什么,但是在这一点上,我认为我们有些偏离主题了。
乔恩·斯基特

2
@CholthiPaulTtiopic:我极力避免以“字符串二进制”的方式思考。二进制数据应被视为二进制数据,而不应被视为文本。我从字面上看过数百个-甚至数千个-关于SO的问题,这些问题基本上归结为人们对这种区别没有足够的重视。
乔恩·斯基特

1
@ still_dreaming_1 PHP调用它们binary strings。(源代码)php.net/manual/en/function.pack.php
Cholthi Paul Ttiopic


116

它是二进制数据的文本编码,其中生成的文本只包含字母,数字以及符号“ +”,“ /”和“ =“。这是通过专门用于文本数据的媒体存储/传输二进制数据的便捷方法。

但是为什么要使用Base-64?将二进制数据转换为立即想到的文本的两种选择是:

  1. 十进制:将每个字节的十进制值存储为三个数字:045 112 101 037等,其中每个字节由3个字节表示。数据膨胀了三倍。
  2. 十六进制:将字节存储为十六进制对:AC 47 0D 1A等,其中每个字节由2个字节表示。数据膨胀了两倍。

Base-64将3个字节(8 x 3 = 24位)映射为跨越6位(6 x 4 = 24位)的4个字符。结果看起来像“ TWFuIGlzIGRpc3Rpb ...”。因此,腹胀仅为原始值的4/3 = 1.3333333倍。


10
我是否正确理解,最好选择64,因为它是可转换为可打印ASCII字符(其中有95个)的2的最高幂?
voho

如果在两种情况下它们都是24位,那么膨胀的1:1不是吗?或当您说4个字符跨越6位时,您是说实际上每个字符有8位,而前两个填充了0吗?
David Klempfner '19

1
@Backwards_Dave每6位用8位表示。因此,腹胀为8:6或4:3。
Ates Goral

82

除了已经说过的以外,还没有列出的两个非常常见的用途是

散列:

哈希是一种单向函数,可将一个字节块转换为另一个固定大小的字节块,例如128位或256位(SHA / MD5)。将结果字节转换为Base64可以更轻松地显示哈希,尤其是在比较校验和的完整性时。哈希在Base64中非常常见,以至于许多人将Base64本身误认为是哈希。

密码学:

由于加密密钥不必是文本而是原始字节,因此有时有必要将其存储在文件或数据库中,Base64方便使用。与生成的加密字节相同。

请注意,尽管Base64通常在加密中使用,但它不是一种安全机制。任何人都可以将Base64字符串转换回其原始字节,因此不应将其用作保护数据的手段,而应仅用作显示或存储原始字节的格式。

证明书

PEM格式的x509证书以base 64编码。http://how2ssl.com/articles/working_with_pem_files/


4
实际上,在许多情况下,将字节存储为字节实际上更容易。即使在数据库中,尤其是在文件中(如果使用固定长度的记录,或者字节是唯一的内容)。当打算将这些字节发送到某处时,特别是在可能丢失位或将某些字节解释为控制代码的通道上,通常使用Base64 。
cHao 2012年

我从未见过以无符号8位整数0、1、255、36编写的哈希,并使用UTF-8或任何其他编码显示它是没有意义的,除了base64之外,您还怎么显示它?加密密钥和加密数据通常存储在配置和XML文件中,而您不能存储原始字节。我同意是否可以将其存储为原始字节,但是base64适用于您无法存储的情况。除了传输之外,base64还有许多用途。这些只是您将在其中看到的两种常见方案。
Despertar

1
您将哈希显示为十六进制,而不是十进制。对于散列,实际上比base64更常见。
cHao 2014年

@cHao是的,这也是常见的。十六进制数字可以表示任何二进制数据,但是base 64的优点是占用更少的空间,因为它使用更多的字符。
Despertar

45

几年前,当引入邮件功能时,它完全是基于文本的,随着时间的流逝,对图像和媒体(音频,视频等)附件的需求应运而生。当这些附件通过Internet发送时(基本上以二进制数据的形式),原始数据中二进制数据被破坏的可能性很高。因此,为解决此问题,BASE64出现了。

二进制数据的问题在于它包含空字符,在某些语言(例如C,C ++)中,空字符表示字符串的结尾,因此以包含NULL字节的原始格式发送二进制数据将阻止文件被完全读取并导致损坏的数据。

例如 :

在C和C ++中,此“空”字符显示字符串的结尾。因此,“ HELLO”的存储方式如下:

你好

72 69 76 76 79 00

00表示“在这里停止”。

现在让我们深入研究BASE64编码的工作原理。

注意点:字符串的长度应为3的倍数。

范例1:

要编码的字符串:“ ace”,长度= 3

1)将每个字符转换为十进制。

a = 97,c = 99,e = 101

在此处输入图片说明

2)将每个十进制更改为8位二进制表示。

97 = 01100001,99 = 01100011,101 = 01100101

合并:01100001 01100011 01100101

3)分成一组6位。

011000 010110 001101 100101

4)计算二进制到十进制

011000 = 24,010110 = 22,001101 = 13,100101 = 37

5)使用base64图表将十进制字符转换为base64。

24 = Y,22 = W,13 = N,37 = l

“ ace” =>“ YWNl”

在此处输入图片说明

范例2:

要编码的字符串:“ abcd” Length = 4,不是3的倍数。因此,要使字符串的长度是3的倍数,我们必须添加2位填充以使length =6。填充位由“ =”符号表示。

需要注意的一点:一个填充位等于两个零00,所以两个填充位等于四个零0000。

因此,让我们开始这个过程:

1)将每个字符转换为十进制。

a = 97,b = 98,c = 99,d = 100

2)将每个十进制更改为8位二进制表示。

97 = 01100001,98 = 01100010,99 = 01100011,100 = 01100100

3)分成一组6位。

011000、010110、001001、100011、011001、00

因此最后6位不完整,因此我们插入了两个填充位,它们等于四个零“ 0000”。

011000、010110、001001、100011、011001、000000 ==

现在,它是相等的。最后的两个等号表示添加了4个零(有助于解码)。

4)计算二进制到十进制。

011000 = 24,010110 = 22,001001 = 9,100011 = 35,011001 = 25,000000 = 0 ==

5)使用base64图表将十进制字符转换为base64。

24 = Y,22 = W,9 = j,35 = j,25 = Z,0 = A ==

“ abcd” =>“ YWJjZA ==”


5
这确实是一个很好的解释
maheshmnj

28

在计算机的早期,当电话线的系统间通信不是特别可靠时,使用了一种快速而肮脏的方法来验证数据完整性:“位奇偶校验”。在这种方法中,发送的每个字节将具有7位数据,而第8位将为1或0,以强制字节中1位的总数为偶数。

因此,0x01将被发送为0x81;0x02将是0x82; 0x03将保留为0x03,依此类推。

为了进一步完善该系统,当定义了ASCII字符集时,仅分配了00-7F字符。(直到今天,所有设置在80-FF范围内的字符均为非标准字符)

当今的许多路由器将奇偶校验和字节转换放入硬件中,迫使连接到它们的计算机严格处理7位数据。这会强制将电子邮件附件(以及所有其他数据,这就是HTTP和SMTP协议基于文本的原因)转换为纯文本格式。

很少有路由器存活到90年代。我严重怀疑其中任何一个都在使用中。


2
谢谢,这是一个很好的讨论点,也是一个有趣的历史课。
Dan Bechard 2015年

26

来自http://en.wikipedia.org/wiki/Base64

术语Base64是指特定的MIME内容传输编码。它也用作任何类似的编码方案的通用术语,该编码方案通过对二进制数据进行数字处理并将其转换为基数64表示形式来进行编码。特殊的基础选择是由于字符集编码的历史:可以选择一组64个字符,这些字符既是大多数编码通用的子集的一部分,并且也是可打印的。这种结合使得数据不太可能在传统上不是8位整洁的系统(如电子邮件)中进行传输。

Base64可用于多种环境:

  • Evolution和Thunderbird使用Base64混淆电子邮件密码[1]
  • Base64可用于传输和存储可能会导致分隔符冲突的文本
  • Base64通常用作快速但不安全的快捷方式来掩盖机密信息,而不会产生加密密钥管理的开销

  • 垃圾邮件发送者使用Base64逃避基本的反垃圾邮件工具,该工具通常不对Base64进行解码,因此无法检测编码邮件中的关键字。

  • Base64用于对LDIF文件中的字符串进行编码
  • 有时使用Base64将二进制数据嵌入XML文件中,使用类似于......的语法,例如Firefox的bookmarks.html。
  • 与政府财政签名打印设备(通常是通过串行或并行端口)进行通信时,还可以使用Base64,以最大程度地减少传输用于签名的收据字符时的延迟。
  • Base64用于对二进制文件(例如脚本中的图像)进行编码,以避免依赖于外部文件。
  • 可以用于将原始图像数据嵌入到CSS属性(例如background-image)中。

11

某些运输协议仅允许传输字母数字字符。试想一下一种情况,其中控制字符用于触发特殊操作和/或仅支持每个字符有限的位宽。Base64将任何输入转换为仅使用字母数字字符+/=作为填充字符的编码。


8

我将在这里描述的Base64的用法有些hack。因此,如果您不喜欢黑客,请不要继续。

当我发现MySQL的utf8不支持4字节的unicode字符时遇到麻烦,因为它使用的是3字节的utf8版本。那么,我为在MySQL的utf8上支持完整的4字节unicode做了什么呢?好吧,当存储到数据库中时,base64编码字符串,而在检索时,base64解码。

由于base64编码和解码非常快,因此上述方法可以完美地工作。

您需要注意以下几点:

  • Base64编码使用的存储量增加了33%

  • 存储在数据库中的字符串将无法被人类读取(您可以将其出售为数据库字符串使用基本加密形式的功能)。

您可以将以上方法用于任何不支持unicode的存储引擎。


6
“您可以将其作为数据库字符串使用基本加密形式的功能来出售”我喜欢您的风格:D
Ercan

7
“您可以将其出售为数据库字符串使用基本加密形式的功能”:D
Alex

1
针对没有base64解码算法的任何人的基本加密形式
rofl

1
@Alex根本不是“可怕的话”。二级敏感数据可以采用base64编码,以使数据库管理员无法读取。不一定总是对每个数据都具有最高级别的加密。例如,如果要向数据库管理员隐藏“注释”,则base64适合该作业。格拉西亚斯!
罗勒·穆萨

1
值得一提的是,MySQL现在确实支持所有Unicode,尽管出于向后兼容的目的,它们的utf8类型仍然仅为三字节。如果您想要真实的东西,请使用utf8mb4。不错的技巧,但不再需要。
TRiG '18 -4-3

7

它用于将任意二进制数据转换为ASCII文本。

例如,以这种方式发送电子邮件附件。


7

当我们通过Web服务传输大型二进制对象(图像)时,我会在实际意义上使用它。因此,当我使用python脚本测试C#Web服务时,可以用一点魔术来重新创建二进制对象。

[在python中]

import base64
imageAsBytes = base64.b64decode( dataFromWS )

1
数据传输速度更快吗?
FelipeM

6

“ Base64编码方案通常用于需要对二进制数据进行编码的情况下,该二进制数据需要通过旨在处理文本数据的媒体进行存储和传输。这是为了确保数据在传输过程中保持完整而无需修改”(Wiki,2017年)

示例如下:您有一个仅接受ASCII字符的Web服务。您想要保存然后将用户的数据传输到其他位置(API),但是收件人希望接收未更改的数据。为此,使用Base64。。。唯一的缺点是,base64编码将比常规字符串多占用33%的空间。

另一个示例:uenc =编码的url = aHR0cDovL2xvYy5tYWdlbnRvLmNvbS9hc2ljcy1tZW4tcy1nZWwta2F5YW5vLXhpaS5odG1s = http://loc.querytip.com/asics-men-s-gel-ka

如您所见,如果要发送上次访问的URL作为参数,则不能在URL中放置字符“ /”,因为我们将破坏“ MOD重写”的GET参数的属性/值规则。

完整的示例为:“ http://loc.querytip.com/checkout/cart/add/uenc/http://loc.magento.com/asics-men-s-gel-kayano-xii.html/product / 93 /


4

通常,我已经看到它用于在只能处理ascii或简单字符集的上下文中对二进制数据进行编码。


3

进一步解释一下Brad所说的话:电子邮件和Usenet的许多传输机制以及其他移动数据的方式都不是“ 8位整洁的”,这意味着标准ascii字符集之外的字符可能会在传输过程中受到干扰-例如, 0x0D可能被视为回车符,并变成了回车符和换行符。Base 64将所有二进制字符映射为几个标准的ascii字母,数字和标点符号,因此不会被这种方式弄乱。


2

Base64

Base64是许多类似编码方案的通用术语,这些编码方案通过对二进制数据进行数字处理并将其转换为base 64表示形式进行编码。Base64术语源自特定的MIME内容传输编码。

当需要对二进制数据进行编码时,通常需要使用Base64编码方案,该二进制数据需要在旨在处理文本数据的媒体上存储和传输。这是为了确保数据在传输过程中保持完整而无需修改。Base64通常用于许多应用程序中,包括通过MIME的电子邮件以及以XML存储复杂数据。


0

Base64可用于许多目的。

主要原因是将二进制数据转换为可传递的数据。

有时,我会使用它将JSON数据从一个站点传递到另一个站点,并将有关用户的信息存储在cookie中。

注意:您可以“使用”它进行加密-我不明白为什么人们会说您不能使用它,并且它不是加密,尽管它很容易被破坏并且被皱眉。加密只不过是将一个数据字符串转换为另一个数据字符串,以后可以解密也可以不解密,这就是base64所做的。



2
你解释的“加密”的定义远远望文生义。这个词已经演变成比起源更具体的东西。
Dan Bechard 2015年

0

一个十六进制数字是一个半字节(4位)。两个半字节组成8位,也称为1字节。

MD5生成一个128位输出,该输出使用32个十六进制数字的序列表示,这些数字又是32 * 4 = 128位。128位构成16个字节(因为1个字节为8位)。

每个Base64字符编码6位(最后一个非填充字符可以编码2、4或6位;最后一个填充字符(如果有)除外)。因此,对于每个Base64编码,一个128位哈希至少需要⌈128/6⌉= 22个字符,如果有的话还要加上pad。

使用base64,我们可以生成所需长度(6、8或10)的编码输出。如果我们选择确定8个字符长的输出,则它仅占用8个字节,而对于128位哈希输出则占用16个字节。

因此,除了安全性,base64编码还用于减少占用的空间。

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.