知乎專欄 | 多維度架構 | 微信號 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); } }