Base64
编码
选出64个字符作为一个基本字符集 A-Z. a-z. 0-9. + / =
- 将每三个字节作为一组,一个是24个二进制位
- 将这24个二进制位分成4组,每组6个二进制位
- 前面每组前面补00 变成8位二进制,最后就扩展成32个二进制位,也就是4个字节
- 根据每个字节,转换成的10进制,对应转码表,进行转换
举例 dog
- 三个字节一组 每个字节转换成ascii码
- d => 100 => 二进制=> 01100100
- o => 111 => 二进制 => 01101111
- g => 103 => 二进制 => 01100111
- 分4组
- 011001。 000110。 111101 100111
- 补0
- 00011001。 00000110。 00111101 00100111
- 转10进制25。6。61。39。
- ZG9n
注意事项
如果字节数不够3位
-
如果只有2位字节 将这两个字节的一共16个二进制位 转换成3组 6 6 4 最后一位数由于只有4位,所以前后各需要补00,这样得到一个三位的base64编码,再在末尾补上一个=号
- Ma
- M => 77 => 01001101
- a => 97 => 01100001
- 00010011,00010110,00000100
- 19 22. 4 => TWE=
-
一个字节的情况,将这个字节的8个二进制位 转换成(6,2)最后一组除了前面加00 后面需要加0000,这样得到的一个base64编码在末尾加上两个=号
- M
- M => 77 => 01001101
- 00010011,00010000
- 19, 16 => TQ==
-
Man
- M转ascii 77
- a转ascii 97
- n转ascii110
- 01001101 01100001 01101110
- 6位分组 010011 010110 000101 101110
- 补0. 00010011 00010110 00000101 00101110
- 19 22 5 46
- base64映射编码 T W F u
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789+/
| 数值 | 字符 | 数值 | 字符 | 数值 | 字符 | 数值 | 字符 | |||
|---|---|---|---|---|---|---|---|---|---|---|
| 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 | / |
解码
从上面的编码算法,每三个字符为一组编码产生4个字符,那么结果便是逆向算法
- 将每4个字符为一组,找到每个字符对应的base64转码值
- 将4个ascii值变成二进制的形式,此时应该是8位的二进制,此时去掉前面的00,每组得到6位,一共24个二进制
- 将剩下的24个二进制分成3份,就说三个字节
- 转换每个字节对应的ascii值
这里写图片描述
举例 T W F u
- base64映射表查找 19 22 5 46
- 二进制010011。010110。000101。 101110
- 四变3 6=>8
- 01001101 01100001 01101110
- 77 97 110
- M a n
算法
1.
var codeMapStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789+/'
/**
* base64编码
* @param {*} str string
*/
function encode(str = '') {
var reg = /([\w\W]{3})(?=[\w\W])/g
// 通过逗号分组,每3个一组
str = str.replace(reg, function (_, $1) {
return `${$1},`
})
var arr = str.split(',')
// 1。每三位分组
return arr.map(function(item) {
return _encode(item)
}).join('')
}
// 每三位字符编码一次
function _encode(str) {
if (!str) {
return ''
}
var binaryStr = ''
for (var i = 0; i < str.length; i++) {
if (str[i]) {
binaryStr += charToBinary(str[i])
}
}
// 这里不能直接new Array(4)如果这样,默认情况下去遍历数组,没有初始化过的数据不会进入遍历
var arr = [undefined, undefined, undefined, undefined]
// 判断str长度
if (str.length === 3) {
arr[0] = '00' + binaryStr.slice(0, 6)
arr[1] = '00' + binaryStr.slice(6, 12)
arr[2] = '00' + binaryStr.slice(12, 18)
arr[3] = '00' + binaryStr.slice(18, 24)
} else if (str.length === 2) {
arr[0] = '00' + binaryStr.slice(0, 6)
arr[1] = '00' + binaryStr.slice(6, 12)
arr[2] = '00' + binaryStr.slice(12) + '00'
} else if (str.length === 1) {
arr[0] = '00' + binaryStr.slice(0, 6)
arr[1] = '00' + binaryStr.slice(6) + '0000'
}
return arr.map(function(item) {
if (!item) {
return '='
}
return codeMapStr[binaryToInt(item)]
}).join('')
}
function charToBinary(char) {
var code = char.charCodeAt()
var binary = code.toString(2)
// 补到8位数
binary = binary.length === 6 ? '00' + binary : binary.length === 7 ? '0' + binary : binary
return binary
}
// 二进制转十进制
function binaryToInt(binary) {
return parseInt(binary, 2)
}
/**
* base64解码
* @param {*} str
*/
function decode(str) {
// 通过分组,每4个一组
var reg = /([\w\W]{4})(?=[\w\W])/g
// 通过逗号分组,每4个一组
str = str.replace(reg, function (_, $1) {
return `${$1},`
})
var arr = str.split(',')
// 1。每三位分组
return arr.map(function(item) {
return _decode(item)
}).join('')
}
// 每四个一组执行
function _decode(str) {
if(!str) {
return ''
}
// 转化成二进制
var binaryStr = ''
for (var i = 0; i < str.length; i++) {
if (str[i] !== '=') {
var code = codeMapStr.indexOf(str[i])
binaryStr += padLeft(code.toString(2), 6, '0')
}
}
var res = [binaryStr.slice(0, 8), binaryStr.slice(8, 16), binaryStr.slice(16, 24)]
return res.filter(function(item) {
return item !== undefined
}).map(function(item) {
return String.fromCharCode(binaryToInt(item))
})
}
// 前面补位
function padLeft (str, len, padChar) {
return new Array(len - str.length + 1).join(padChar || '') + str
}
module.exports = {
encode: encode,
decode: decode
}
