密码学:一文看懂Base64算法 |
您所在的位置:网站首页 › idea是什么加密算法 › 密码学:一文看懂Base64算法 |
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文件中给出了如下字符映射表:
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算法来完成的。 应用场景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=这样处理后的密钥看起来就比较容易接受,可以将其放到合同书中,发放给其他人。 数字证书数字证书可以使用多种格式存储,常见的包括: X.509 PEM 格式: X.509 PEM 格式是一种常见的证书格式,通常使用Base64编码,以ASCII文本的形式存储。PEM文件通常以.pem、.crt、.cer、.key等扩展名结尾。PEM 格式证书通常如下: -----BEGIN CERTIFICATE----- MIIFqzCCBJOgAwIBAgIQAf2jJAY75k6nqYDL5OwZpzANBgkqhkiG9w0BAQwFADB5 [...] u+Dvi9IJOZd/21Bbsb/6bER5epqCyl/wI -----END CERTIFICATE----- DER 格式: DER(Distinguished Encoding Rules)格式是二进制编码的 X.509 证书格式,通常以.der、.cer、.crt等扩展名结尾。 PKCS#12 格式(PFX 或 P12): PKCS#12 是一种可包含公钥、私钥和证书链等信息的存储格式。通常以.p12、.pfx等扩展名结尾。 JKS 格式: JKS(Java KeyStore)是Java中常见的密钥存储格式,可以用于存储证书和密钥。通常以.jks扩展名结尾。 PKCS#7 / P7B 格式: PKCS#7 或 P7B 格式用于存储证书链,通常以.p7b、.p7c等扩展名结尾。 CAdES 格式: CAdES(CMS Advanced Electronic Signatures)是用于电子签名的一种格式,扩展了 CMS(Cryptographic Message Syntax)。通常以.p7m、.p7s等扩展名结尾。 参考《Java加密与解密艺术》 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |