密码学:一文看懂Base64算法

发布时间:2024年01月04日

请添加图片描述

前言

Base64常常在我们开发中出现,我们可能只知道它是一串乱码(看不懂的符号),知道有时候知道我们需要把一些数据进行base64编码,有时候需要进行Base64解码。但是却不知道它的作用是什么?它存在的意义是什么?还有它是如何生成的?如何编码和解码?
上述的疑问相信在你读完本篇文章之后烟消云散。

下面开始正文。

什么是Base64?

Base64是什么?
它和加密解密操作有什么关系吗?
让我们先来看看以下这段看似诡异的乱码:

54K55Liq5YWz5rOo77yM5piv5a+55oiR5oyB57ut5Yib5L2c55qE5pyA5aSn55qE6byT5Yqx77yB

没错,这就是经过Base64编码后的字符串。对它解码后,我们获得以下内容

点个关注,是对我持续创作的最大的鼓励!

这段文字在经过Base64编码后面目全非,而经过Base64解码后又能恢复本来面目,这很有加密解密的意味。不过Base64算法并不是加密算法,仅仅是加密算法的近亲。Base64算法的转换方式很像古典加密算法中的单表置换算法。下面来介绍这种常用于电子邮件的算法。

Base64算法的由来

Base64算法最早应用于解决电子邮件传输的问题。在早期,由于 “历史问题” 电子邮件只允许ASCII码字符。如果要传输一封带有非ASCII码字符的电子邮件,当它通过有 “历史问题” 的网关时就可能出现问题。这个网关很可能会对这个非ASCII码字符的二进制位做调整,即将这个非ASCII码的8位二进制码的最高位置为0。此时用户收到的邮件就会是一封纯粹的乱码邮件了。基于这个原因产生了Base64算法。
对ASCII码概念感觉模糊的同学可以去看看这篇文章:一文看懂所有字符编码标准

Base64算法的定义

Base64是一种基于64个 字符的编码算法,根据RFC2045的定义:“Base64内容传送编码是一种以任意8位字节序列组合的描述形式,这种形式不易被人直接识别”。

经过Base64编码后的数据会比原始数据略长,为原来的4/3倍。

经Base64编码后的字符串的字符数是以4为单位的整数倍。

RFC2045还规定,在电子邮件中,每行为76个字符,每行末需添加一个回车换行符(“\r\n”),不论每行是否够76个字符,都要添加一个回车换行符。但在实际应用中,往往根据实际需要忽略了这一要求。
在RFC2045文件中给出了如下字符映射表:

在这里插入图片描述
这张字符映射表中,Value指的是十进制编码,Encoding指的是字符,共映射了64个字符,这也是Base64算法命名的由来。映射表的最后一个字符是等号,它是用来补位的。有经验的朋友一看到字符串末尾有个等号,就会联想到Base64算法了。
其实,Base64算法还有几个同胞兄弟,如Base32和Base16算法。为了能在http请求中以Get方式传递二进制数据,由Base64算法衍生出了Url Base64算法。

Url Base64算法主要是替换了Base64 字符映射表中的第62和63个字符,也就是将“+”和“/”符号替换成了“-”和“_”符号。但对于补位符“=”,一种建议是使用"~ "符号,另一种建议是使用“.”符号。其中,由于“~”符号与文件系统冲突,不建议使用。

而对于“.”符号,如果出现连续两次,则认为是错误。对于补位符的问题,Bouncy Castle和Commons Codec有差别,Bouncy Castle使用"."作为补位符,而Commons Codec则完全杜绝使用补位符。

有关Base16、Base32和Url Base64算法的详细内容,可以参考RFC4648

Base64算法与加密算法的关系

Base64算法有编码和解码操作可充当加密和解密操作,还有一张字符映射表充当了密钥。

单表置换算法,Base64算法正是运用了这一思想,将原文经二进制转换后与字符映射表相对应,得到“密文”。Base64算法经常用做一个简单的“加密”来保护某些数据。

尽管如此,Base64算法仍不能叫做加密算法。Base64算法公开,这一点与柯克霍夫原则并无违背,但充当密钥的字符映射表公开,直接违反了柯克霍夫原则,而且Base64算法的加密强度并不够高。因此,不能将Base64算法看做我们所认可的现代加密算法。

Base64算法虽不能称为加密算法,但其变换法则遵从了单表置换算法。也正因如此,Base64算法成为加密算法学习最好的范例。尤其是在自定义加密算法研制方面,Base64算法是一个很不错的参考。如果我们将Base64算法做少许改造,并将字符映射表调整、保密,改造后的Base64算法就具备了加密算法的意义!除此之外,Base64算法常作为密钥、密文和证书的一种通用存储编码格式,与加密算法形影不离。

实现原理

Base64算法主要是将给定的字符以与字符编码(如ASCII码,UTF-8码)对应的十进制数为基准,做编码操作:
1)将给定的字符串以字符为单位,转换为对应的字符编码 (如ASCII码)
2)将获得的字符编码转换为二进制码
3)对获得的二进制码做分组转换操作,每3个8位二进制码为一组,转换为每4个6位二进制码为一组(不足6位时低位补0) 。这是一个分组变化的过程,3个8位二进制码和4个6位二进制码的长度都是24位(3x8=4x6=24)
4)对获得的4-6二进制码补位,向6位二进制码添加2位高位0,组成4个8位二进制码。
5)将获得的4-8二进制码转换为十进制码
6)将获得的十进制码转换为Base64字符表中对应的字符

我们对字符串“A”进行Base64编码:

字符             A
ASCII码          65
二进制码         01000001
4-6二进制码      010000       010000
4-8二进制码      00010000     00010000
十进制码         16           16
字符表映射码      Q            Q           =   =

由此,字符串“A”经过Base64编码后就得到了“QQ==”这样一个字符串。

Base64解码操作就是编码操作的逆运算,反推上述流程很容易获得原文信息。

"A"经过Base64编码后的字符串末尾带着2个等号。很显然,当原文的二进制码长度不足24位,最终转换为十进制码时也不足4项,这时就需要用等号补位。如果原文只有一个字符,那么经过Base64编码后的字符串末尾会有2个等号。
经Base64编码后的字符串最多只会有2个等号,这是因为:

余数 = 原文字节数 MOD 3

这是一个简单的算术问题,余数的值只可能是0、1或2。

余数为0时,则原文字节数恰好是3的倍数,没有等号。

这个尾巴;余数为1时,则为了让Base64编码后的字符数是4的倍数,要补2个等号。

同理,余数为2时,则要补1个等号。

所以,通常判别一个字符串是不是Base64编码的第一步操作就是判断这个字符串末尾是不是有等号。

这同时也说明,Base64编码后的字符串是以4个字符为单位,其长度只能是4个字符的整数倍。

本文开篇对“点个关注,是对我持续创作的最大的鼓励!”这个字符串做了Base64编码后获 得了一个长度为 76个字符的字符串“54K55Liq5YWz5rOo77yM5piv5a+55oiR5oyB57ut5Yib5L2c55qE5pyA5aSn55qE6byT5Yqx77yB”,正好说明了这一点。

非ASCII码字符编码

Base64算法很好地解决了非ASCII码字符的传输问题,譬如中文字符的传输问题。
ASCII码可以表示十进制范围为0~ 127的字符,对应二进制范围是00000000~01111111。ASCII码包括阿拉伯数字、大小写英文字母和一些控制符,但却没有包含双字节编码的字符,如中文字符。因此有了GB2312、GBK和UTF-8等编码。GB2312、GBK用2个字节表示一个汉字,UTF-8编码则用3个字节表示一个汉字。Base64算法实现时,对6位二进制码添加高2位0,恰恰保护了非ASCII码字符在通过有问题的网关时不发生问题。

我们以字符串“密”为例,字符串“密“对应的UTF-8编 码就是-27,-81,-122。我们对其做如下Base64编码:

字符               密
UTF-8码            -27           -81            -122
二进制码           11100101      10101111       10000110
4-6二进制码        111001        011010         111110         000110
4-8二进制码        00111001      00011010       00111110       00000110
十进制码           57            26             62             6
字符表映射码       5             a              +              G

字符串“密”经过Base64编码后得到字符串“5a+G”。

传递模型

在这里插入图片描述
我们通过时序图来描述一次基于Base64算法的消息传递。这里,我们仍以甲方与乙方交互数据举例。甲方作为数据的发送方,乙方作为数据的接收方。其操作流程如下:
1)甲方对数据做Base64编码处理
2)甲方将编码后的数据发送给乙方
3)乙方获得数据后对数据做Base64解码处理
要操作Base64算法并不复杂。甲乙双方可以通过上述流程完成一次数据通信,或是单方面地进行电子邮件发送,亦或是仅仅为了传输非ASCII码的字符信息等。

这些操作在实际应用中常常是通过Base64算法来完成的。

应用场景

Base64算法广泛应用于电子邮件传输,以及密钥和证书文件的文本方式保存。在数据保密要求强度不高的情况下,可以使用Base64算法做简单的数据“加密”。

电子邮件传输

电子邮件一般都会使用Base64算法,我们截取一段电子邮件信息:

Content-Type: text/plain;
charset="utf8"
Content-Transfer-Encoding: base64
6L+Z5piv5LiA5bCB5rWL6K+V6YKu5Lu277yB

在这封邮件里,我们看到了我们需要的信息

  • 字符集编码: charset charset="utf8
  • 内容传输编码: Content-Transfer-Encoding:base64
  • 邮件内容: 6L+Z5piv5LiA5bCB5rWL6K+V6YKu5Lu277yB

通过上述信息,我们确定无疑这是一封使用了Base64编码的邮件,并且邮件的内容使用的是UTF-8编码的字符集。由此,我们只需要通过上述Base64算法的实现类一Base64Coder完成解码操作。毋庸置疑,这份邮件的内容是:“这是一封测试邮件!“

网络数据传输

不论是通过HTTP的Get方式以URL参数传输数据,还是通过Post方式以数据体传输数据,都能发现Base64编码藏匿其中
只要通信双方在通信前约定好字符编码和字符映射表,改良后的Base64算法就可以在HTTP环境中以Get/Post方式传递二进制数据。这时的Base64算法,无疑成为了一种简单的加密算法。

密钥存储

在计算机的世界里,密钥就是一段二进制的数据。
密钥的二进制表现形式使得它的安全性大为提升,但却大大降低了它的可读性。通常我们希望密钥可以有一个容易理解的表现形式(如经过Base64编码后的字符串),以增强它的可读性并且方便密钥的发放。如甲方向乙方发送密钥,可以将密钥以二进制形式转化为Base64编码后的字符串形式,通过安全途径以文档形式发放给乙方,密钥很可能被要求写在合同中。
Base64算法的优势恰恰是在基于二进制编码格式的转换上,这一点使得二进制的密钥通常以Base64编码的形式展现。

另一种类似的效果是将二进制串转为十六讲制串,如消息摘要结果。以下是一个经过Base64编码处理后DES的密钥:

I6ttWOmtSo8=

这样处理后的密钥看起来就比较容易接受,可以将其放到合同书中,发放给其他人。

数字证书

数字证书可以使用多种格式存储,常见的包括:

  1. X.509 PEM 格式:
    X.509 PEM 格式是一种常见的证书格式,通常使用Base64编码,以ASCII文本的形式存储。PEM文件通常以.pem.crt.cer.key等扩展名结尾。

PEM 格式证书通常如下:
-----BEGIN CERTIFICATE----- MIIFqzCCBJOgAwIBAgIQAf2jJAY75k6nqYDL5OwZpzANBgkqhkiG9w0BAQwFADB5 [...] u+Dvi9IJOZd/21Bbsb/6bER5epqCyl/wI -----END CERTIFICATE-----

  1. DER 格式:
    DER(Distinguished Encoding Rules)格式是二进制编码的 X.509 证书格式,通常以.der.cer.crt等扩展名结尾。

  2. PKCS#12 格式(PFX 或 P12):
    PKCS#12 是一种可包含公钥、私钥和证书链等信息的存储格式。通常以.p12.pfx等扩展名结尾。

  3. JKS 格式:
    JKS(Java KeyStore)是Java中常见的密钥存储格式,可以用于存储证书和密钥。通常以.jks扩展名结尾。

  4. PKCS#7 / P7B 格式:
    PKCS#7 或 P7B 格式用于存储证书链,通常以.p7b.p7c等扩展名结尾。

  5. CAdES 格式:
    CAdES(CMS Advanced Electronic Signatures)是用于电子签名的一种格式,扩展了 CMS(Cryptographic Message Syntax)。通常以.p7m.p7s等扩展名结尾。

参考

《Java加密与解密艺术》

文章来源:https://blog.csdn.net/Shujie_L/article/details/135382596
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。