Base64加密转换原理与代码实现
一、Base64实现转换原理
它是用64个可打印字符表示二进制所有数据方法。由于2的6次方等于64,所以可以用每6个位元(bit)为一个单元,对应某个可打印字符。我们知道三个字节(byte)有24个位元,就可以刚好对应于4个Base64单元,即3个字节需要用4个Base64的可打印字符来表示。

· 可打印符号:
在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中一般有所不同。但是,我们经常所说的Base64另外2个字符是:“+/”。这64个字符,所对应表如下:
编号 字符 编号 字符 编号 字符 编号 字符 0 A 16 Q 32 g 48 w 1 B 17 R 33 h 49 x 2 C 18 S 34 i 50 y 3 D 19 T 35 j 51 z 4 E 20 U 36 k 52 0 5 F 21 V 37 l 53 1 6 G 22 W 38 m 54 2 7 H 23 X 39 n 55 3 8 I 24 Y 40 o 56 4 9 J 25 Z 41 p 57 5 10 K 26 a 42 q 58 6 11 L 27 b 43 r 59 7 12 M 28 c 44 s 60 8 13 N 29 d 45 t 61 9 14 O 30 e 46 u 62 + 15 P 31 f 47 v 63 /
仔细思考一下,你会很快发现,一个问题,就是每次转换的字节数不一定就是24的整数倍,会出现有多余不足六位的情况,在base64中处理的方法是加零凑够六位,但是这样一来在解码的时候就会出现多余的位 这该怎么办呢? base64想到了一个很好的解决办法。这个办法就是在 base64凑零的同时,还要满足凑出来的位数是8的倍数,不然就加一个或者两个特殊的六位 = 符号。为什么是一个或者两个=符号呢? 因为多个8位转为6位 只会出现 剩余 2位,4位的情况,剩余2位 只需要一个 表示六位的 = 便可变为8的整数;而剩余4位 需要两个表示6位的 = 便可以变成16 是8的整数。然后在解密的时候不解析 =即可。
之所以位的总数需要凑成8的倍数,是因为base64主要用于加密后的数据传送,而在传送机制中都认为传送的最小单位是按照字节算的,所以不能出现不是位总数不是8的倍数的情况,在接收到数据后,按顺序将6位的base64直接按照顺序解密成字节就完成解密了。
· 转换过程:
① 将三个byte(字节)的数据,先后放入一个24bit(位)的缓冲区中,先来的byte占高位。数据不足 3 byte的话,于缓冲区中剩下的bit用0补足。
② 然后,每次取出6个bit,按照其值选择 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ 中的字符作为编码后的输出。不断进行,直到全部输入数据转换完成。
③ 如果最后剩下两个输入数据,在编码结果后加1个“=”;
如果最后剩下一个输入数据,编码结果后加2个“=”;
如果没有剩下任何数据,就什么都不要加,这样才可以保证资料还原的正确性。
编码后的数据比原始数据略长,为原来的4/3。
| 文本 | M | a | n | |||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ASCII编码 | 77 | 97 | 110 | |||||||||||||||||||||
| 二进制位 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 |
| 索引 | 19 | 22 | 5 | 46 | ||||||||||||||||||||
| Base64编码 | T | W | F | u | ||||||||||||||||||||
M的Ascii码是77,前六位对应值为19,对应base64字符是T,如此类推。其它字符编码就可以自动转换得到!我们看看另外不是刚好是3个字节的情况!
| 文本(1 Byte) | A | |||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 二进制位 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | ||||||||||||||||
| 二进制位(补0) | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | ||||||||||||
| Base64编码 | Q | Q | = | = | ||||||||||||||||||||
| 文本(2 Byte) | B | C | ||||||||||||||||||||||
| 二进制位 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | x | x | x | x | x | x | ||
| 二进制位(补0) | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | x | x | x | x | x | x |
| Base64编码 | Q | k | M | = | ||||||||||||||||||||
二、Base64转换代码实现
public class Base64Util {
private static final char last2byte = (char) Integer.parseInt("00000011", 2);
private static final char last4byte = (char) Integer.parseInt("00001111", 2);
private static final char last6byte = (char) Integer.parseInt("00111111", 2);
private static final char lead6byte = (char) Integer.parseInt("11111100", 2);
private static final char lead4byte = (char) Integer.parseInt("11110000", 2);
private static final char lead2byte = (char) Integer.parseInt("11000000", 2);
private static final char[] encodeTable = new char[]
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
public Base64Util() {
}
public static String encode(byte[] from) {
StringBuilder to = new StringBuilder((int) ((double) from.length * 1.34D) + 3);
int num = 0;
char currentByte = 0;
int i;
for (i = 0; i < from.length; ++i) {
for (num %= 8; num < 8; num += 6) {
switch (num) {
case 0:
currentByte = (char) (from[i] & lead6byte);
currentByte = (char) (currentByte >>> 2);
case 1:
case 3:
case 5:
default:
break;
case 2:
currentByte = (char) (from[i] & last6byte);
break;
case 4:
currentByte = (char) (from[i] & last4byte);
currentByte = (char) (currentByte << 2);
if (i + 1 < from.length) {
currentByte = (char) (currentByte | (from[i + 1] & lead2byte) >>> 6);
}
break;
case 6:
currentByte = (char) (from[i] & last2byte);
currentByte = (char) (currentByte << 4);
if (i + 1 < from.length) {
currentByte = (char) (currentByte | (from[i + 1] & lead4byte) >>> 4);
}
}
to.append(encodeTable[currentByte]);
}
}
if (to.length() % 4 != 0) {
for (i = 4 - to.length() % 4; i > 0; --i) {
to.append("=");
}
}
return to.toString();
}
}
Base64加密转换原理与代码实现的更多相关文章
- Base64加密解密原理以及代码实现(VC++)
Base64加密解密原理以及代码实现 转自:http://blog.csdn.net/jacky_dai/article/details/4698461 1. Base64使用A--Z,a--z,0- ...
- Base64加密解密原理以及代码实现
1. Base64使用A--Z,a--z,0--9,+,/ 这64个字符. 2. 编码原理:将3个字节转换成4个字节( (3 X 8) = 24 = (4 X 6) )先读入3个字节,每读一个字 ...
- Base64编码转换原理
Base64编码,是我们程序开发中经常使用到的编码方法.它是一种基于用64个可打印字符来表示二进制数据的表示方法.它通常用作存储.传输一些二进制数据编码方法.它其实只是定义用可打印字符传输内容一种方法 ...
- base64加密和解码原理和代码
Base64编码,是我们程序开发中经常使用到的编码方法.它是一种基于用64个可打印字符来表示二进制数据的表示方法.它通常用作存储.传输一些二进制数据编码方法!也是MIME(多用途互联网邮件扩展,主要用 ...
- Java 和JS Base64加密
项目在登录.注册等场景实现时,经常会用到用户信息前端加密,然后项目后端二次解密,避免信息直接在浏览器上以明文显示. 本文主要介绍了base64加密的方式处理代码,不支持中文 源码如下: base64. ...
- Java Base64加密、解密原理Java代码
Java Base64加密.解密原理Java代码 转自:http://blog.csdn.net/songylwq/article/details/7578905 Base64是什么: Base64是 ...
- Base64图片编码原理,base64图片工具介绍,图片在线转换Base64
Base64图片编码原理,base64图片工具介绍,图片在线转换Base64 DataURI 允许在HTML文档中嵌入小文件,可以使用 img 标签或 CSS 嵌入转换后的 Base64 编码,减少 ...
- Java的Base64加密原理
出自: http://www.cnblogs.com/winner-0715/p/5920269.html http://www.cnblogs.com/koliop090/p/5203553.h ...
- 【代码笔记】iOS-3DES+Base64加密解密
一,工程目录. 二,代码. RootViewController.m #import "RootViewController.h" #import "NSString+T ...
随机推荐
- select2 清除选中项解决办法
在项目中使用select2:选中项 设置可清除. 代码中加上了allowClear : true $.get("/Work/Ajax/Select.ashx", function ...
- mongodb集群配置分片集群
测试环境 操作系统:CentOS 7.2 最小化安装 主服务器IP地址:192.168.197.21 mongo01 从服务器IP地址:192.168.197.22 mongo02 从服务器IP地址: ...
- VUE 微信开发
1.工具 1.电脑版微信客户端window版本(1.x.x 亲测可以在谷歌浏览器进行微信授权登录,版本越来越好)或者用微信开发工具.很久之前就是用这个方法搞定用chrome进行微信登录授权. 2.us ...
- redis总结问题
简单回顾了redis,在这过程中 首先得了解redis是什么,redis的运用场景,redis支持哪些数据格式,redis如何操作数据,redis如何实现高可用 redis是什么: Redis 是一个 ...
- Ubuntu 16.04 安装 JDK 1.8
系统环境 Ubuntu 16.04; JDK 1.8 配置安装 1.首先从oracle下载jdk 1.8,我下载的版本是jdk-8u131-linux-x64.tar.gz,运行tar zvxf jd ...
- 理解OpenShift(3):网络之 SDN
理解OpenShift(1):网络之 Router 和 Route 理解OpenShift(2):网络之 DNS(域名服务) 理解OpenShift(3):网络之 SDN 理解OpenShift(4) ...
- 知识点:Mysql 基本用法之流程控制
流程控制 一. 条件语句 if 语句实例: delimiter // CREATE PROCEDURE proc_if () BEGIN declare i int default 0; if i = ...
- MAC地址表、ARP缓存表以及路由表
一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的.在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据 ...
- vim常用操作和使用技巧
vi是linux与unix下的常用文本编辑器,其运行稳定,使用方便,本文将分两部分对其常用操作技巧和配置进行阐述,其中参考了网上的一些文章,对作者表示感谢 PART1 操作技巧 说明: 以下的例子中 ...
- 详解vue-cli脚手架项目-package.json
该随笔收藏自: 详解vue-cli脚手架项目-package.json package.json是npm的配置文件,里面设定了脚本以及项目依赖的库. npm run dev 这样的命令就写在packa ...