个人理解
加密方式、传输、转化二进制、字符对应关系
一、Base64 简介
数据编码方式、常用于数据传输。针对二进制数据,进行base64编码。其他数据常用JSON。
二、Base64 原理
Base64是一种基于64个可打印字符来表示二进制数据的表示方法。便于传输和拷贝。
在编码中,需要6个Bit位表示:26 = 64
在计算机中,3个Byte的二进制,相当于24个Bit,4个Base64的字符。即 “3 Byte = 24 Bit = 4 Base64”。
Base64可打印的字符:A-Z、a-z、0-9,一般情况下用 +、/,在URL Salf的模式下用 -、_。补位用 =。
将 byte 数组中的每一个 byte 都转换成 8 位 bit, 组成一串二进制数据,然后按 6 位进行分割,再将每 6 位转换成一个 bit ,将转换后的 bit 作为 index ,去码表中查找对应显示的字符。
![](https://img-blog.csdnimg.cn/2fd495cfd92840eba278e57df11b3ba2.png)
![](https://img-blog.csdnimg.cn/f42c1e89677b4b9ca54305aa16f814c4.png)
三、Base64 实现
1、JAVA版
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
private static final char[] toBase64 = {
'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', '+', '/'
};
private static final char[] toBase64URL = {
'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', '-', '_'
};
/**
* 把10进制的数字转换成64进制
*
* @param number 10进制
* @return 64进制
*/
private static String compressNumber(long number) {
char[] buf = new char[64];
int charPos = 64;
int radix = 1 << 6;
long mask = radix - 1;
do {
buf[--charPos] = toBase64URL[(int) (number & mask)];
number >>>= 6;
} while (number != 0);
return new String(buf, charPos, (64 - charPos));
}
/**
* 把64进制的字符串转换成10进制
*
* @param compress 64进制
* @return 10进制
*/
private static long unCompressNumber(String compress) {
long result = 0;
for (int i = compress.length() - 1; i >= 0; i--) {
for (int j = 0; j < toBase64URL.length; j++) {
if (compress.charAt(i) == toBase64URL[j]) {
result += ((long) j) << 6 * (compress.length() - 1 - i);
}
}
}
return result;
}
private static final Snowflake SNOWFLAKE = IdUtil.getSnowflake(1,1);
/**
* 获取字符串id(雪花算法)
* @return id
*/
public static String nextIdStr() {
return SNOWFLAKE.nextIdStr();
}
/**
* 获取 id(雪花算法)
* @return id
*/
public static long nextId() {
return SNOWFLAKE.nextId();
}
/**
* 获取64进制雪花算法 id
* @return id(64进制)
*/
public static String getId() {
return compressNumber(nextId());
}
/**
* 获取10进制雪花算法 id
* @return id(10进制)
*/
public static long getId(String compress) {
return unCompressNumber(compress);
}
四、附录
A1、Base64 编码
序号 | 二进制 | 可打印字符 | 序号 | 二进制 | 可打印字符 | 序号 | 二进制 | 可打印字符 | 序号 | 二进制 | 可打印字符 |
0 | 00000 | A | 16 | 010000 | Q | 32 | 100000 | g | 48 | 110000 | w |
1 | 000001 | B | 17 | 010001 | R | 33 | 100001 | h | 49 | 110001 | x |
2 | 000010 | C | 18 | 010010 | S | 34 | 100010 | i | 50 | 110010 | y |
3 | 000011 | D | 19 | 010011 | T | 35 | 100011 | j | 51 | 110011 | z |
4 | 000100 | E | 20 | 010100 | U | 36 | 100100 | k | 52 | 110100 | 0 |
5 | 000101 | F | 21 | 010101 | V | 37 | 100101 | l | 53 | 110101 | 1 |
6 | 000110 | G | 22 | 010110 | W | 38 | 100110 | m | 54 | 110110 | 2 |
7 | 000111 | H | 23 | 010111 | X | 39 | 100111 | n | 55 | 110111 | 3 |
8 | 001000 | I | 24 | 011000 | Y | 40 | 101000 | o | 56 | 111000 | 4 |
9 | 001001 | J | 25 | 011001 | Z | 41 | 101001 | p | 57 | 111001 | 5 |
10 | 001010 | K | 26 | 011010 | a | 42 | 101010 | q | 58 | 111010 | 6 |
11 | 001011 | L | 27 | 011011 | b | 43 | 101011 | r | 59 | 111011 | 7 |
12 | 001100 | M | 28 | 011100 | c | 44 | 101100 | s | 60 | 111100 | 8 |
13 | 001101 | N | 29 | 011101 | d | 45 | 101101 | t | 61 | 111101 | 9 |
14 | 001110 | O | 30 | 011110 | e | 46 | 101110 | u | 62 | 111110 | + 或 - |
15 | 001111 | P | 31 | 011111 | f | 47 | 101111 | v | 63 | 111111 | / 或 _ |
末尾填充 | = |
A2、思考
1、Base64 编码一定要填充 = 吗?
当不足3Byte数据转换过程中,末尾可以填充的 =,也可以不填充。
当进行填充时,可以防止多个Base64拼接一起,解码失败。
2、Base64 是否认为是一种加密方式?
加密定义:以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。
在使用 Base64 的过程中,已经遵从常用的编码标准: RFC 4648 以及 RFC 2045,使用标准的码表来进行处理,并不能算得上是“加密”,但如果在进行编解码的过程中,使用特殊的码表,可以让编码的内容不容易被解码出来,也可以实现对原始内容的“加密”功能。