深入理解 Base64 底层原理

article/2025/9/13 9:05:41

Base64 是一种常见数据编码方式,常用于数据传输。对于移动开发者来讲,网络请求中会经常使用到。对 JSON 熟悉的同学都知道,JSON 的序列化工具都不支持将 byte 数组直接放入 JSON 数据中,针对这种二进制数据,在处理的时候,都需要进行 Base64 编码,然后将编码后的字符串放入到 JSON 中。 从刚入行到现在,Base64 是一个非常常用的功能,从网上“搬运” Base64 编解码工具到使用 Android SDK 中内置的 Base64。虽熟练使用,但终未深入了解 Base64 的底层机制。

巧的是,近期工作中,又遇到了 Base64 的相关事情,于是去相对深入了解了 Base64 的相关内容。以下仅作为自身学习记录。

1. Base64 定义

Base64 是一种基于 64 个可打印字符来表示二进制数据的表示方法,用人话讲叫可以把二进制数据打印在控制台上,可以很好的拷贝以及传输。

在编码中使用的 64 个可打印字符只需要 6 个 Bit 位就可以表示: 2 6 = 64 2^6 = 64 26=64

在计算机世界中,3 个 Byte 的二进制数据相当于 24 个 Bit , 因此在编码时需要对应 4 个 Base64 的字符来表示。

Base64 的可打印字符集包含了字母 A-Za-Z、数字 0-9, 这样就有了 62 个字符,另外两个在不同的系统中可能会不同,我们一般使用的为 +/,在 URL Safe 的模式下为 -_

Base64 码表:

Base64 码表

2. Base64 转换

我们将 byte 数组中的每一个 byte 都转换成 8 位 bit, 组成一串二进制数据,然后按 6 位进行分割,再将每 6 位转换成一个 bit ,将转换后的 bit 作为 index ,去码表中查找对应显示的字符。

编码示例如下:

编码示例

如上图所示,将 LZC 转换成 Base64 编码的可打印的字符串为 TFpD。 从这个示例可以看出来,刚好可以将 3 个 byte 转成 4 个 byte。

聪明的你可能已经发现存在的问题,如果要编码的原始 byte[] 的长度不能被三整除应该怎么处理呢?

在码表中,除了编码中用到的 64 个字符,在末尾还有一个填充字符: = ,用来填充不足的位数。

举例说明:

Padding 处理

3. Base64 encode 代码实现(Java 版)

  1. 将现有的 3 个 byte a, b, c编码成 Base64 的串
final char[] base64 = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M','N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm','n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
byte a = 'L';
byte b = 'Z';
byte c = 'C';int index1 = (a >> 2) & 0b00111111;
int index2 = ((a << 4) & 0b00110000) | ((b >> 4) & 0b00001111);
int index3 = ((b << 2) & 0b00111100) | ((c >> 6) & 0b00000011);
int index4 = c & 0b00111111;byte[] result = new byte[]{(byte) base64[index1], (byte) base64[index2], (byte) base64[index3], (byte) base64[index4]
};
System.out.println(new String(result));// TFpD
  1. 将现有的 2 个 byte a, b 编码成 Base64 的串
byte a = 'Z';
byte b = 'C';int index1 = (a >> 2) & 0b00111111;
int index2 = ((a << 4) & 0b00110000) | ((b >> 4) & 0b00001111);
int index3 = ((b << 2) & 0b00111111);
byte[] result = new byte[]{(byte) base64[index1], (byte) base64[index2], (byte) base64[index3], '='
};
System.out.println(new String(result));// WkM=
  1. 将现有的 1 个 byte a 编码成 Base64 的串
byte a = 'L';
int index1 = (a >> 2) & 0b00111111;
int index2 = ((a << 4) & 0b00111111);
byte[] result = new byte[]{(byte) base64[index1], (byte) base64[index2], '=', '='
};
System.out.println(new String(result));// TA==

从代码中,可以看到前文所述的转换步骤。 但在计算 index2 以及 index3 的时候,还是有点绕,有没有更好的计算方式呢?

JDK 的 Base64 的实现中,看到了一种新的实现方式。 在 Java 中,一个 int 型的数占 4 个 byte ,因此可以将要转换的 3 位 byte 放在一个 int 数据中。

如下图所示,将 LZC 三个 byte 放入一个 int 型变量中去:

int 型变量存储三个 byte

代码实现:

byte a = 'L';
byte b = 'Z';
byte c = 'C';
int bits = (a & 0xFF) << 16 | (b & 0xFF) << 8 | (c & 0xFF);// 10011000101101001000011

拿到 bits 后,就可以直接进行位运算,取出对应的 4 个 6 位二进制数。 代码实现如下:

// 0x3f == 0b00111111
int index1 = (bits >> 18) & 0x3F;
int index2 = (bits >> 12) & 0x3F;
int index3 = (bits >> 6) & 0x3F;
int index4 = bits  & 0x3F;byte[] result = new byte[]{(byte) base64[index1], (byte) base64[index2], (byte) base64[index3], (byte) base64[index4]
};
System.out.println(new String(result));

4. 思考一:Base64 编码一定要添加填充(Padding)吗?

在前文中,对于不足 3 个 byte 的数据转换过程中,需要在编码后的串中加入填充字符 = ,让最后输出的 Base64 的串正好是 4 的整数倍。那么问题来了,为什么要使用 = 号进行填充?不填充可以吗?

android.utils.Base64 的实现中,有一个叫 NO_PADDING 的 flag。如果在使用的过程中,传入了这个 flag,最后的输出结果就是没有埋充 = 的结果。 因此,在进行编码的时候,对于不足 3 个 byte 的数据处理时,也可以不进行填充。

当然,如果进行填充,在解码的时候,能够更加简单的去处理,直接将编码的串,4 个字符一组进行处理,而不用判断字符数量,走不同的解码逻辑。当然,Padding 还可以用来标识编码结束,来防止多个 Base64 拼接到一起后,解码失败。

5. 思考二:Base64 是否可以认为是一种加密方式呢?

Base64 是一种编码方式,将原始数据转换成了一种可打印的字符串。 在工作中,也经常会有人称之为 Base64 加密 ,按照 加密 的定义:

以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。

对于 Base64 来讲,在使用的过程中,早已经遵从了常用的编码标准: RFC 4648 以及 RFC 2045,使用标准的码表来进行处理,并不能算得上是“加密”,但如果,在进行编解码的过程中,使用特殊的码表,可以让编码的内容不容易被解码出来,也可以实现对原始内容的“加密”功能。

6. 最后

在文中,有关 Base64 的编码过程中的原理以及代码实现都已经存在,如果有兴趣,可以尝试一下去实现解码的代码编写,可以更好的理解其中的原理。 知其然,知其所以然,写代码犹如神助。


http://chatgpt.dhexx.cn/article/jwnowfCA.shtml

相关文章

Base64基本原理

1.什么是Base64 Base64是一种基于64个可打印字符来表示二进制数据的编码方式&#xff0c;是从二进制数据到字符的过程。 原则上&#xff0c;计算机中所有内容都是二进制形式存储的&#xff0c;所以所有内容&#xff08;包括文本、影音、图片等&#xff09;都可以用base64来表示…

一篇文章彻底弄懂Base64编码原理

在互联网中的每一刻&#xff0c;你可能都在享受着Base64带来的便捷&#xff0c;但对于Base64的基础原理又了解多少&#xff1f;今天这篇博文带领大家了解一下Base64的底层实现。 Base64的由来 目前Base64已经成为网络上常见的传输8Bit字节代码的编码方式之一。在做支付系统时&…

Base64编码原理

一、Base64是什么 base 64、base 32、base 16 编码建议标准 https://www.ietf.org/rfc/rfc4648.txt Base64是基于64种字符的编码算法&#xff0c;即将数据使用64种字符表示&#xff0c;编码后的Base64字符串长度 通常为原来的3-4倍。&#xff08;补充&#xff1a;Base32就是…

Base64原理

前言 Base64是什么?它和加解密操作有什么关系吗?我们看一下下边这段字符串: aGVsbG8gd29ybGQ= 这就是经过Base64编码后的字符串,对它进行Base64解码,获得它原来的内容: hello world 这有点加密解密的意味,不过Base64并不能称为加密算法,仅仅是加密算法的近亲,可以称之…

Base64原理解析

一. Base64编码由来 为什么会有Base64编码呢&#xff1f;因为有些网络传送渠道并不支持所有的字节&#xff0c;例如传统的邮件只支持可见字符的传送&#xff0c;像ASCII码的控制字符就 不能通过邮件传送。这样用途就受到了很大的限制&#xff0c;比如图片二进制流的每个字节不可…

base64加密原理详解

Base64编码&#xff0c;是我们程序开发中经常使用到的编码方法。它是一种基于用64个可打印字符来表示二进制数据的表示方法。它通常用作存储、传输一些二进制数据编码方法&#xff01;也是MIME&#xff08;多用途互联网邮件扩展&#xff0c;主要用作电子邮件标准&#xff09;中…

Base64基本原理及简单应用

1.什么是Base64 Base64是一种基于64个可打印字符来表示二进制数据的编码方式,是从二进制数据到字符的过程。原则上,计算机中所有内容都是二进制形式存储的,所以所有内容(包括文本、影音、图片等)都可以用base64来表示。 2.Base64编码原理 Base64编码之所以称为Base64,是因…

一文详解 Base64编码原理

最近在看Android的签名与验签机制&#xff0c;其中涉及到 MD5、SHA2、SHA256 等摘要算法&#xff0c;也涉及到 Base64 编码机制。这里先从简单的入手&#xff0c;记录一下 Base64 编码机制的原理。 一、Base64由来 Base64 是一种编码方式&#xff0c;最早出现在电子邮件传输协…

在Unity中导入fbx格式文件

unity中是以米为单位&#xff0c;要想让3dmax中建的模型导入到unity中与unity自带的3d object尺寸一致&#xff0c;最直接的办法是将3dmax中的系统单位也设成米。在三维软件里设置 在菜单->自定义->单位设置&#xff1a; 导出FBX文件前 &#xff0c;我们需要注意如下问…

读取FBX文件踩坑清单

FBX文件得到了许多3D制图软件与3D游戏引擎的兼容&#xff0c;其发展趋势大好。因此若要编写一款3D图形系统&#xff0c;对FBX格式的支持是必经之路&#xff08;或者使用插件形式&#xff09;。笔者尝试在百度、必应等搜索引擎&#xff0c;外加fbxsdk实例的帮助下&#xff0c;读…

查看fbx文件

查看fbx文件可以使用 1.auto fbx review 2.unity 导入Inport New Asset 找到文件夹导入 拖拽到scene中即可查看

「.XD 文件 」用什么软件打开?

1、什么是「.XD 文件 」 「.XD 文件 」其实是 Adobe XD 文件格式。而 Adobe XD 是一款基于矢量的一站式 UI/UX 设计工具&#xff0c;可以进行移动应用和网页设计与原1型制作&#xff0c;从早期的构思和低保真设计&#xff0c;一直到令人印象深刻的动画和逼真的原型&#xff0c…

Unity Fbx转Prefab工具

1.功能描述 a.可将fbx直接导出prefab。 b.同时为prefab预先按需挂载脚本文件。 c.同时为挂载的脚本设置参数&#xff0c;绑定资源等。 d.批量化处理&#xff0c;递归遍历算法&#xff0c;高效可扩展。 2.实现方式 a.Editor类 using Lean.Touch; using Main; using System; usi…

将FBX文件导入Unity3d中

在Project中找到选择Assets: 点击鼠标右键出现下拉列表&#xff0c;在下拉列表中选择“Import New Asset..."选项&#xff1a; 点击后选择你要导入的FBX文件&#xff0c;导入&#xff1a; 然而这样导入的模型并不会显示贴图&#xff0c;要让模型可以正常显示贴图&#xff…

【pymxs】max文件导出fbx文件

1. 前言 .max格式是Autodesk公司下的3dsmax软件的通用格式&#xff0c;许多软件出于商业考虑都有自己的格式&#xff0c;例如网易云下载的音乐。 这也就意味着.max文件只能用Autodesk的产品打开&#xff0c;即3dsmax或maya。 Autodesk的产品均是非开源、封闭式的&#xff0c…

Fbx文件解析(一)——FBX SDK for Windows环境配置

Fbx文件解析&#xff08;一&#xff09;——FBX SDK for Windows环境配置 一、下载并安装FBX SDK 下载网址&#xff1a;http://www.autodesk.com/fbx 找到与自己Windows对应、与自己的VS版本对应的SDK版本&#xff0c;下载并按照安装步骤安装。安装时选择的安装文件夹就是下…

pmx转fbx的具体步骤

本文主要讲述了在Windows10环境下&#xff0c;通过blender将pmx格式文件转化为fbx文件的具体步骤 本文主要包括以下三个部分&#xff1a; 一、blender下载与安装二、cats插件安装三、pmx格式转换为fbx格式 一、blender下载与安装 1.下载blender到电脑上 blender下载 建议下载…

关于unity导出FBX文件

最近有项目需求需要根据特殊文件来绘制自定义图形&#xff0c;考虑到其他编辑器对此文件的共用&#xff0c;所以将图形导出为FBX格式。 在网上找到了一个git仓库在这也记录分享一下&#xff1a; Git仓库:UnityFBXExporterhttps://github.com/Ymiku/UnityFBXExporter 插件功能…

加载FBX模型文件

深入理解加载FBX模型文件 每个模型文件都有自己的格式&#xff0c;有自研引擎的模型格式&#xff0c;有AutoDesk提供的模型文件格式&#xff0c;比如FBX模型文件&#xff0c;因为Unity与UE4引擎的使用而备受关注&#xff0c;FBX文件是AutoDesk提供的SDK&#xff0c;已经封装好了…

FBX格式转换为GLTF/GLB格式

有小伙伴说通过blende将fbx转glb/gltb格式的模型无法在web端加载&#xff0c;或glb模型无法打开&#xff0c;比如腾讯地图加载gltf。 这里个大家分享一个插件 可以将fbx格式转换为glb格式 window版本 链接&#xff1a;https://pan.baidu.com/s/17wwI-hmezg9-sOnHZNn_uw?pwd1…