最近开发过程当中常常会须要Base64编码,MD5,加密等功能,这些频繁使用的小工具要常常到网上找,并且还都不太好用,就本身开发了一个, codoolo。在实现Base64的过程,也学到了不少。这篇文件记录Base64相关的知识,欢迎指正。
Base64早已经被普遍使用了,尤为是Multipurpose Internet Mail Extensions (MIME)。html
wikipedia中对Base64的定义:安全
Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation.
简单来讲,Base64使用了指定的64个字符对数据编码,而这64个字符中不包括特殊字符(以避免被一些应用认为是控制字符,若是ftp,ssh等),这样通过编码的数据能够在网络中安全的传输。网络
首先须要挑选64个字符。RFC 4648定义了Base64的字符集:ssh
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/工具
下图显示如何将字符串“xyz”编码为“eH16”的过程编码
第二步和第三步实际上是一系列位操做,并不须要真的转换,这里为了将编码过程阐述清楚,加了这两个步骤。加密
因为6位正好能够表示64,因此每3个8位的字符(24bit)能够编码为4个Base64字符(4个6bit=24bit)。但编码后的每一个字符的存储仍然须要8位。这意味着Base64编码后的存储空间增长了1/3spa
Base64使用6 bits重组数据,但重组后的每一个字符仍然须要8 bit的存储空间。因此Base64是用较小的字符集表示数据,但存储空间却所以增长了,所谓有一利必有一弊。code
在上面的Base64字符集中包括了 '+/' ,而通常的URL和文件名中,不能使用这两个字符,因此RFC4686提议使用另一个字符集:orm
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
而具体用哪一个字符集,要考虑使用的场景。好比只是在项目内部使用,编解码均可控,那么就可使用第二个,甚至可使用一个自定义的字符集。但若是是将数据给第三方,那么使用第一个字符集更好,由于大部分库的实现都使用了第一个字符集。
咱们刚刚说了如何将3个字符应用Base64编码,但若是字符串的长度不是3的倍数怎么办?
若是最后还有两个字符须要编码:
好比"xy",2个字符有16 bits,那么前12 bits能够编码为"eH",对于剩下的4 bits,在右侧填充2个0,因此第三个字符是"k"。有时,网络中传输的数据长度是未知的,这时为了肯定知道数据是否截止,则须要将编码的数据补齐为4的倍数。对于Base64编码,使用 = 来补齐,也就是第65个字符。
若是最后只有一个字符,过程相似:
须要注意的是,最后使用了2个 == 来补齐。
请问,若是一个Base64编码的最后有3个=,即===,这是一个合法的Base64编码么?
咱们上面讨论编码的时候,都假设输入的是ASCII,即字符是0x00-0xFF之间的。那若是输入的字符是UTF-8呢?好比:
“こんにちは” 或者 “你好”
通常有两种方式来处理:
因此在实现codoolo时, 若是输入的是非ASCII码,会提示选择一个转换器:
了解了编码过程,相信解码就比较简单了,也就是将上面的过程逆向执行就能够。
说实话,我一直在使用Base64编码,到从没想过一个Base64编码也要有这么多须要注意的地方,并且还有问题:
咱们之后接着聊。