Home | 簡體中文 | 繁體中文 | 雜文 | 知乎專欄 | Github | OSChina 博客 | 雲社區 | 雲棲社區 | Facebook | Linkedin | 視頻教程 | 打賞(Donations) | About
知乎專欄多維度架構 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者”

第 203 章 Encode & Decode

目錄

203.1. MIME (BASE64) 專題
203.1.1. Linux Command base64
203.1.2. PHP Base64
203.1.2.1. base64_encode
203.1.2.2. base64_decode
203.1.3. Python Base64
203.1.4. perl base64
203.1.5. Java Base64
203.1.5.1. Java 7
203.1.5.2. Java 8
203.1.6. C/C++ Base64
203.2. Uuencode
203.2.1. PHP uuencode
203.3. Quoted-Printable
203.3.1. C Quoted-Printable
203.3.2. Java Quoted-Printable
203.3.3. Python Quoted-Printable
203.4. Base58
203.4.1. php
203.4.2. Java Base58

203.1. MIME (BASE64) 專題

什麼是Base64?

按照RFC2045的定義,Base64被定義為:Base64內容傳送編碼被設計用來把任意序列的8位位元組描述為一種不易被人直接識別的形式。

為什麼要使用Base64?

在設計這個編碼的時候,我想設計人員最主要考慮了3個問題:

  1. 是否加密?

  2. 加密算法複雜程度和效率?

  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 - Base64

203.1.1. Linux Command base64

$ cat file | base64
		

203.1.2. PHP Base64

203.1.2.1. base64_encode

base64_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==  */
?>
		
			

203.1.2.2. base64_decode

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

203.1.3. Python Base64

編碼:b64encode

			
import base64
base64.b64encode('This is an encoded string')
			
			

此示例將顯示:

'VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw=='

解碼:

			
import base64
base64.b64decode('VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==')
			
			

此示例將顯示:

This is an encoded string

203.1.4. perl base64

perl -MMIME::Base64 -e 'print encode_base64("netkiller");'

perl -MMIME::Base64 -e 'print decode_base64("bmV0a2lsbGVy");'
		

203.1.5. Java Base64

203.1.5.1. Java 7

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) {

	    }
	}
}
		

203.1.5.2. Java 8

			
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);
	}

}

			
			

203.1.6. C/C++ Base64