知乎专栏 |
什么是Base64?
按照RFC2045的定义,Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。
为什么要使用Base64?
在设计这个编码的时候,我想设计人员最主要考虑了3个问题:
是否加密?
加密算法复杂程度和效率?
如何处理传输?
加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是“防君子不防小人”。即达到一眼望去完全看不出内容即可。 基于这个目的加密算法的复杂程度和效率也就不能太大和太低。和上一个理由类似,MIME协议等用于发送Email的协议解决的是如何收发Email,而并不是如何安全的收发Email。因此算法的复杂程度要小,效率要高,否则因为发送Email而大量占用资源,路就有点走歪了。
但是,如果是基于以上两点,那么我们使用最简单的恺撒法即可,为什么Base64看起来要比恺撒法复杂呢?这是因为在Email的传送过程中,由于历史原因,Email只被允许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通过有“历史问题”的网关时就可能会出现问题。网关可能会把最高位置为0!很明显,问题就这样产生了!因此,为了能够正常的传送Email,这个问题就必须考虑!所以,单单靠改变字母的位置的恺撒之类的方案也就不行了。关于这一点可以参考 RFC2046。 基于以上的一些主要原因产生了Base64编码。
参考邮件正文 Content-Transfer-Encoding: base64
OpenSSL - Base64base64_encode
(PHP 3, PHP 4, PHP 5)
base64_encode -- 使用 MIME base64 对数据进行编码
说明
string base64_encode ( string data )
base64_encode() returns 使用 base64 对 data 进行编码。设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输,例如电子邮件的主体。
Base64-encoded 数据要比原始数据多占用 33% 左右的空间。
例子 1. base64_encode() 示例
<?php $str = 'This is an encoded string'; echo base64_encode($str); ?>
此示例将显示:
VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==
例子 2. stream_filter_append() 示例
<?php $fp = fopen('php://output', 'w'); stream_filter_append($fp, 'convert.base64-encode'); fwrite($fp, "This is a test.\n"); fclose($fp); /* Outputs: VGhpcyBpcyBhIHRlc3QuCg== */ echo "\n============================================\n"; $fp = fopen('php://output', 'w'); stream_filter_append($fp, 'convert.base64-decode'); fwrite($fp, "VGhpcyBpcyBhIHRlc3QuCg=="); fclose($fp); /* Outputs: This is a test. */ echo "============================================\n"; $param = array('line-length' => 8, 'line-break-chars' => "\r\n"); $fp = fopen('php://output', 'w'); stream_filter_append($fp, 'convert.base64-encode', STREAM_FILTER_WRITE, $param); fwrite($fp, "This is a test.\n"); fclose($fp); /* Outputs: VGhpcyBp : cyBhIHRl : c3QuCg== */ ?>
base64_decode
(PHP 3, PHP 4, PHP 5)
base64_decode -- 对使用 MIME base64 编码的数据进行解码
说明
string base64_decode ( string encoded_data )
base64_decode() 对 encoded_data 进行解码,返回原始数据,失败则返回 FALSE。返回的数据可能是二进制的。
例子 1. base64_decode() 示例
<?php $str = 'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw=='; echo base64_decode($str); ?>
此示例将显示:
This is an encoded string
编码:b64encode
import base64 base64.b64encode('This is an encoded string')
此示例将显示:
'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw=='
解码:
import base64 base64.b64decode('VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==')
此示例将显示:
This is an encoded string
perl -MMIME::Base64 -e 'print encode_base64("netkiller");' perl -MMIME::Base64 -e 'print decode_base64("bmV0a2lsbGVy");'
import java.io.*; public class base64Test { public static void main(String[] args) { try { String text = "This is an encoded string"; //Convert a string to base64 string byte[] buf = text.getBytes(); String encode = new sun.misc.BASE64Encoder().encode(buf); System.out.println(encode); // Convert base64 string to a string buf = new sun.misc.BASE64Decoder().decodeBuffer(encode); String decode = new String(buf); System.out.println(decode); } catch (IOException e) { } } }
package cn.netkiller.test; import java.nio.charset.StandardCharsets; import java.util.Base64; public class Base64Test { public static void main(String[] args) { final String text = "http://www.netkiller.cn/index.html"; final String encoded = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8)); System.out.println(encoded); final String decoded = new String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8); System.out.println(decoded); } }
package cn.netkiller.security; import java.io.UnsupportedEncodingException; import java.util.Base64; public class Base64Test { public Base64Test() { // TODO Auto-generated constructor stub } public static void main(String[] args) throws UnsupportedEncodingException { // TODO Auto-generated method stub String asB64 = Base64.getEncoder().encodeToString("some string".getBytes("utf-8")); System.out.println(asB64); // 输出为: c29tZSBzdHJpbmc= // 解码 byte[] asBytes = Base64.getDecoder().decode("c29tZSBzdHJpbmc="); System.out.println(new String(asBytes, "utf-8")); // 输出为: some string // 但由于URL对反斜线“/”有特殊的意义,因此URL编码需要替换掉它,使用下划线替换 String basicEncoded = Base64.getEncoder().encodeToString("subjects?abcd".getBytes("utf-8")); System.out.println("Using Basic Alphabet: " + basicEncoded); String urlEncoded = Base64.getUrlEncoder().encodeToString("subjects?abcd".getBytes("utf-8")); System.out.println("Using URL Alphabet: " + urlEncoded); } }