| 知乎專欄 | 多維度架構 | 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者” |
什麼是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);
}
}