深入理解Base64编码原理

开发 前端
Base64编码是一种广泛应用的编码方法,它将二进制数据转换为可打印的ASCII字符集,特别适用于数据传输和存储场景。

前言

上篇文章有涉及到Base64编码的内容,今天我们再来详细了解一下Base64的编码原理以及应用场景。

通过这篇文章你能够学习到:

  • 什么是Base64,为什么需要Base64?
  • Base64的编码原理
  • Base64的应用场景

什么是Base64?

Base64是一种用于传输8bit字节数据的编码方式,Base64 的字符集包含 64 个字符(A-Z、a-z、0-9、+、/)以及补位的=

⚠️需要注意的是它只是一种编码方式,并不是加密方式!!!因为对于Base64来讲,它没有密钥的概念,这意味着任何人都能轻松地将Base64编码的数据还原为原始字符。

尽管如此,不少人仍误将其当作加密工具来使用,这在具备基本技术知识的人眼中,无异于未加密处理...

为什么需要Base64编码?

Base64编码最初主要应用于邮件传输协议中,由于这些协议仅支持ASCII字符的传递,导致直接传输二进制文件(如图片、视频等)成为不可能。为了解决这一问题,Base64被设计出来,它能够将二进制文件内容转换成仅包含ASCII字符的编码形式,从而实现在邮件传输协议中安全、有效地传递二进制数据。

编码原理

Base64 编码的核心原理是将输入数据(多为二进制形式)转换成特定字符序列。具体步骤为:首先将输入数据分割成每三个字节(共24位)一组,接着将这24位分割为四个6位的块(因为Base64中每个字符代表6位二进制数据)。最后,通过查找表将这些6位块映射为相应的Base64字符。

base64字符集

上面我们提到标准的Base64一般包含64个字符再加一个补位的=

  • 大写字母:A-Z(26 个字符)
  • 小写字母:a-z(26 个字符)
  • 数字:0-9(10 个字符)
  • 特殊字符:+ 和 /(2 个字符)
  • 补位字符:=

编码步骤

  1. 分组:将输入数据按每三个字节一组进行划分,每组组成一个24位的二进制数据块。
  2. 分割:将每个24位的数据块进一步分割成四个6位的数据块。
  3. 字符映射:通过查找字符集,将每个6位数据块映射为字符集中的对应字符。
  4. 填充处理:若输入数据的字节数非3的倍数,则在数据末尾添加=字符作为填充,以确保编码结果的长度符合Base64规范。

怎么理解这些步骤?

以南玖的南拼音为例

首先将字符对应的二进制位表示出来

图片图片

刚好nan是3个字节,它们的二进制位正好组成了一个24位的二进制块

接着把这个二进制块分割成4个6位的数据块

图片图片

最后通过查找Base64编码对照表,找到每个6位数据块对应的字符

图片图片

最终nan编码为bmFu

由于nan的字节数正好是3的倍数,所以它不需要补位,编码后也就不会出现=

补位

如果字节数不是3的倍数,那么余数可能是1或2,所以补位也需要分两种情况。

  • 余数为1,二进制末尾补4个0,最后多出来的这个字符会编码成2个base64字符,最后再补两个=

比如宋的拼音song,余数为1

图片图片

在这基础上最后还得补上2个=,最终song编码为c29uZw==

  • 余数为2,二进制末尾补2个0,编码后末尾再补1个=

比如ab,余数为2

图片图片

最终ab编码为YWI=

验证

在javaScript中可以调用btoa来进行base64编码

图片图片

动手实现一下Base64编解码

base64编码

// 自定义base64编码
const customEncrypt = (str: string) => {
    // base64字符集
    const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
    // 将字符串转中的每个字符转换成8位二进制
    const binaryStr = str.split('').map(char => {
        const binary = char.charCodeAt(0).toString(2)
        return binary.padStart(8, '0')
    }).join('')

    // 将二进制字符串按6位分割
    const binaryArr = binaryStr.match(/.{1,6}/g) || []

    // 如果最后一组不是6位的倍数,后面补0
    const last = binaryArr[binaryArr.length - 1]
    if(last?.length % 6 !== 0) {
        binaryArr[binaryArr.length - 1] = last.padEnd(6, '0')
    }

    // 将6位的二进制转换成10进制
    const decimalArr = binaryArr.map(binary =>parseInt(binary, 2))

    // 根据10进制的值获取base64字符
    let base64Str = decimalArr.map(decimal => base64Chars[decimal]).join('')

    // 补位
    while(base64Str.length % 4 !== 0) {
        base64Str += '='
    }
    return base64Str
}

基本按照上面的编码步骤实现即可

验证

console.log('btoa', btoa('song'))
console.log('自定义加密', customEncrypt('song'))

图片图片

base64解码

解码的过程基本就是与编码反过来

// 自定义base64解码
const customDecrypt = (str: string) => {
    // base64字符集
    const base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
    // 将base64字符转换成10进制
    const decimalArr = str.split('').map(char => base64Chars.indexOf(char))

    // 将10进制转换成6位二进制
    const binaryArr = decimalArr.map(decimal => decimal.toString(2).padStart(6, '0'))

    // 将6位的二进制拼接
    const binaryStr = binaryArr.join('')

    // 将8位的二进制转换成字符
    const charArr = binaryStr.match(/.{1,8}/g) || []
    return charArr.map(binary =>String.fromCharCode(parseInt(binary, 2))).join('')
}

验证

console.log('atob', atob('c29uZw=='))
console.log('自定义解码', customDecrypt('c29uZw=='))

图片图片

思考🤔

按照这个思路我们是不是可以实现一个比Base64更安全的伪加密方法

比如:

  • 更换字符集
  • 更换二进制分割手段

应用场景

数据传输

Base64编码是一种在HTTP文本协议中传输二进制数据的常用方法。由于HTTP协议本质上是基于文本的,它限制了只能传输可打印的ASCII字符(范围从32到126),这包括字母、数字、标点符号和一些特殊符号。然而,二进制数据包含许多不在这个范围内的字符,因此无法直接通过HTTP协议进行传输。Base64编码不仅解决了在HTTP协议中传输二进制数据的问题,还确保了数据的完整性和可读性。

数据存储

Base64 编码常用于存储二进制数据,如数据库中的图像、文件等,因为它将数据转换为可打印字符,避免了二进制数据在存储过程中可能出现的问题。

在前端页面实现中,为了提高加载效率,简单图片通常会选择直接内嵌而非加载外部资源。然而,图片是二进制数据,直接嵌入并不简单。幸运的是,现代浏览器普遍支持Data URLs功能,该功能通过Base64编码将图片或其他文件的二进制数据转换为文本字符串,从而可以方便地嵌入到网页中。这样,就无需进行额外的外部资源加载,有助于减少页面加载时间。

协议编码

Base64编码最初主要应用于邮件传输协议中,由于这些协议仅支持ASCII字符的传递,导致直接传输二进制文件(如图片、视频等)成为不可能。为了解决这一问题,Base64被设计出来,它能够将二进制文件内容转换成仅包含ASCII字符的编码形式,从而实现在邮件传输协议中安全、有效地传递二进制数据。

总结

Base64编码是一种广泛应用的编码方法,它将二进制数据转换为可打印的ASCII字符集,特别适用于数据传输和存储场景。然而,重要的是要认识到,Base64编码本身并不具备数据加密或安全保护的功能。在需要处理敏感信息时,仅凭Base64编码是远远不够的,必须结合适当的加密技术和安全传输协议(如HTTPS)来确保信息的安全性和隐私性。

责任编辑:武晓燕 来源: 前端南玖
相关推荐

2021-09-07 08:59:09

编码Base64解码

2014-02-20 10:28:28

JavaScriptBase64

2024-02-28 23:07:42

GolangBase64编码

2019-07-23 08:55:46

Base64编码底层

2021-03-05 09:10:19

base64编码

2024-07-31 10:22:49

Go语言编码

2021-03-10 10:55:51

SpringJava代码

2022-11-04 09:43:05

Java线程

2024-03-12 00:00:00

Sora技术数据

2022-09-05 08:39:04

kubernetesk8s

2024-11-01 08:57:07

2018-01-22 17:02:48

Python字符编码ASCII

2020-08-10 18:03:54

Cache存储器CPU

2024-04-15 00:00:00

技术Attention架构

2021-08-26 05:27:08

Base64 字节流算法

2023-09-19 22:47:39

Java内存

2020-03-26 16:40:07

MySQL索引数据库

2022-09-26 08:01:31

线程LIFO操作方式

2022-01-14 12:28:18

架构OpenFeign远程

2020-03-17 08:36:22

数据库存储Mysql
点赞
收藏

51CTO技术栈公众号