Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

第 162 章 Encode & Decode

目录

162.1. MIME (BASE64) 专题
162.1.1. Linux Command base64
162.1.2. PHP Base64
162.1.3. Python Base64
162.1.4. perl base64
162.1.5. Java Base64
162.1.6. C/C++ Base64
162.2. Uuencode
162.2.1. PHP uuencode
162.3. Quoted-Printable
162.3.1. C Quoted-Printable
162.3.2. Java Quoted-Printable
162.3.3. Python Quoted-Printable
162.4. Base58
162.4.1. php
162.4.2. Java Base58

162.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

162.1.1. Linux Command base64

$ cat file | base64
		

162.1.2. PHP Base64

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

162.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

162.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

162.1.4. perl base64

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

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

162.1.5. Java Base64

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

	    }
	}
}
		

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

}

			
			

162.1.6. C/C++ Base64