Base64 encoding/decoding常见于各种authentication和防盗链的实现当中。彻底搞懂它绝对提升团队troubleshooting的底气。我们从纯手工方式编码解码开始,然后看看学到的技能怎么样应用在实际的troubleshooting 中。

准备工作:我们应知道一个byte有8个bits,并且知道怎么表示它。

我们应该comfortable with hex, binary and decimal 之间的conversion.

有一张现成的ASCII table. (网上有很多,我下面附一个直接带binary value的)

Base64 Table

Base64 Encoding的原理

大白话是这样。给定一个bits序列,从最左开始,按顺序每6-bit 为一组进行分组,这样每一组可以表示最多2的6次方,也就是64个字符。这是为什么它叫Base64的原因。

这样分组,最后即最右边的一组如果正好有6-bit, 分组就完成。如果不够6-bit, 就要做一个alignment / padding的处理。有两步。第一步,用binary 0 (bit 的值为0)补齐到6-bit. 如果补过的bit 序列正好落在byte boundary,则分组完毕;如若不然,继续第二步,补到下一个最近的byte boundary, 不过不是用0去pad, 而是用等号字符“=”, 用1个或者2个等号去补, 别忘了,一个等号占6个bits.

用数学的方式正规一点的描述是这样。

给定一个长度为L的bit 序列,L可以被8整除 ( 这也是byte boundary含义), 我们需要找到两个正整数M和N, 使得: L <= M <= N, 其中 M要能够被6整除, N is either L or L + 8.

根据这个描述可以得出下面这些结论:最后得到的长度为N的bit 序列也是落在byte boundary上,即N可以被8 整除。

L除以6的余数只有三种可能: 0,2, 4, 对应于三种不同的padding scenarios.

M - L 的 值只可能为: 0, 2, 4, 道理同上

N – M的值只可能为: 0, 6,12, 同样的,这是对应于三种不同的padding scenarios.

纯手工Base64编码

Given an input string “a”,

Step 1: 将它convert 成 bit 序列

查ASCII table, 我们得到它的binary value 即 bit 序列: 01100001

这是一个长度为8的初始序列。

Step 2: 按6个bits 一组分组

011000 01

Step 3: 最右组只有2 个bit, 不够6 bits, 需要补4个0

011000 010000

至此我们可以得到两个字符:

011000 = 2 ** 4 + 2 ** 3 = 16 + 8 = 24, 查Base64 table, 对应于24的字符是 Y.

010000 = 2 ** 4 = 16, 同样查Base64 table, 对应于16的字符是 Q

很多Base64的实现,到这就结束了。小写 a, 经过Base64编码之后就是YQ.

Step 4: 这原始bit 序列长度为8, Step 3补了4个0, 变成12,不能被8整除,继续补。

我们知道从12开始,下一个被8整除的值是24, 所以我们要补24 – 12 = 12个bits. 在这种情况下我们补等号字符,一个字符占6 bits,所以我们补两个”= “.

如果做了这一步,小写 a, 经过Base64编码之后就是YQ== .

纯手工Base64 解码

Given YQ==,

Step 1: 去掉“=”的padding, 得到 YQ, 同时知道pad了12 bits 到byte boundary.

Step 2: 根据Base64 table convert “YQ” to bit 序列 011000 010000

Step 3: 去掉 最右边pad的4个0

因为原始字符也就是要decode过去的字符是跳 8的,现在有12 bits, 很快可以确定最右4 bits 是padding.

从这种工作方式我们可以看到,既然最右4 bits无论如何都是要去掉的,这4 bits 可以是任何2 ** 4 = 16个值中的一个,而不影响decoding的结果。举几个例子:

0110000 010001 = YR

0110000 010010 = YS

0110000 010011 = YT

0110000 011110 = Ye

0110000 011111 = Yf

下面是用Python Bas64 module decoding的结果,验证上面所讲。

>>> base64.b64decode("YR==")

'a'

>>> base64.b64decode("YT==")

'a'

>>> base64.b64decode("YU==")

'a'

>>> base64.b64decode("YV==")

'a'

>>> base64.b64decode("YW==")

'a'

>>> base64.b64decode("YY==")

'a'

>>> base64.b64decode("YZ==")

'a'

>>> base64.b64decode("Ya==")

'a'

>>> base64.b64decode("Yb==")

'a'

>>> base64.b64decode("Yf==")

'a'

>>> base64.b64decode("Ye==")

'a'

>>>

Step 4: 按8-bit 分组, 得到 011000 01, 这个就是”a”.

实例分析

Linkedin发现如果他们修改防盗链token的最后一位,authentication仍然可以通过,要我们解释。

Token in question是这样的:

bs3xODAExQFZthY2LF1EqbuVtq4veLftiHILz3pXn13Ai5DzRYmdCZ8O9FAQwI4zceyBpEJO6secbKz9rGNMfBVeNaplwLNVqQwAXSR-grVQGJkz91pqdmVBbrwCpGto5IazBV8XDMJUIGCGZOdld2REqemD4cvDoLdeN3itZirB2FGfMHPxhP0

如果把末尾0换成1,2, 3, authentication 仍旧可以通过。

前面学到的东西可以马上应用。思路是这样的:

Token 长度为183, 所以bit 序列的长度为183 * 6 = 1098. 因为1098 没有落在byte boundary, 我们可以立即确定encoding 的Step 4省略了,即没有pad “=”.

因为1098 / 8 = 137 r2, 我们可以确定 最右的2 bit 是padding. 如前所述, 这两个bits 可以是 任何 2 ** 2 = 4个值中的一个,而不影响decoding的结果。

00 = 0

01 = 1

10 = 2

11 = 3

至此Linkedin 的问题彻底解释清楚。

读了这一篇,你应该可以回答为什么有的Base64-encoded的values 末尾没有等号,有的有一个等号,有的有两个等号,以及为什么多个values会decode到相同的value. If necessary, you should be able to base64 encode and decode pretty much anything MANUALLY.

token要加编码decode吗_彻底弄明白Base64 编码相关推荐

  1. python字符编码在哪里_快速入手Python字符编码

    前言 对于很多接触python的人而言,字符的处理和语言整体的温顺可靠相比显得格外桀骜不驯难以驾驭. 文章针对Python 2.7,主要因为3对的编码已经有了很大的改善并且实际原理一样,更改一下操作命 ...

  2. java解码base64的png图片_使用PHP对图片进行base64编码和解码(png、jpg,声音、视频)...

    为什么要对图片base64编码 base64是网络上最常见的传输8Bit字节代码的编码方式之一.base64主要不是加密,它主要的用途是把一些二进制数转成普通字符用于网络传输.由于一些二进制字符在传输 ...

  3. 一文轻松明白 Base64 编码原理

    把图片丢进浏览器,打开sources能看到一长串字符串,这是图片的Base64编码.这一长串编码到底是怎么生成的呢? 我们接下来探索一下base64编码的原理 Base64 名称的由来 Base64编 ...

  4. golang中base64编码_MySQL中如何将字符串转为base64编码?

    点击蓝字关注我们!每天获取最新的编程小知识! 源 / php中文网      源 / www.php.cn 在MySQL中,TO_BASE64()函数将字符串转换为以base-64编码的字符串并返回结 ...

  5. java 二进制 base64编码_java 按字节读写二进制文件(Base64编码解码)

    最近在做项目时遇到这样一个需求:依次读取本地文件夹里所有文件的内容,转为JSON,发送到ActiveMQ的消息队列, 然后从MQ的消息队列上获取文件的信息,依次写到本地.常见的文件类型,比如.txt ...

  6. MySQL怎么存base64编码_MySQL中如何将字符串转为base64编码?

    在MySQL中,TO_BASE64()函数将字符串转换为以base-64编码的字符串并返回结果.(相关推荐:<MySQL教程>) 语法TO_BASE64(str) 其中str是需要编码的字 ...

  7. python 文件编码的识别_【python】python编码方式,chardet编码识别库

    环境: python3.6 需求: 针对于打开一个文件,可以读取到文本的编码方式,根据默认的文件编码方式来获取文件,就不会出现乱码. 针对这种需求,python中有这个方式可以很好的解决: 解决策略: ...

  8. idea 编码扫描插件_代码神器:拒绝重复编码,这款IDEA插件了解一下

    作者:HeloWxlhttp://www.jianshu.com/p/e4192d7c6844 Easycode是idea的一个插件,可以直接对数据的表生成entity.controller.serv ...

  9. 编码规范重要性_沟通比您的编码技能更重要

    编码规范重要性 TL; DR (TL;DR) Communication is More Important Than Your Coding Skills 沟通比您的编码技能更重要 A few sh ...

最新文章

  1. golang 获取 磁盘 内存 占用
  2. php 详解spl_autoload_register()函数
  3. 《C#设计模式》PPT及源码分享
  4. 使用OC进行iOS截屏,同时保证清晰度
  5. Qt之模式、非模式、半模式对话框
  6. Reddit热议:为什么PyTorch比TensorFlow更快?
  7. 物流机器人小车的运动控制与定位
  8. python连接php_PHP+Python,轻量维护超轻松
  9. 再提手机上网应该包月计费
  10. 微信小程序自定义弹窗,禁止page页面滚动。
  11. 市场部商业计划PPT模板
  12. Mysql 省市区字典(带层级,带经纬度,带拼音)字典版
  13. 手机扫描电脑百度网盘二维码,二维码无法刷新的解决办法
  14. 解决Macm苹果笔记本电脑白屏
  15. linux驱动编写之十六(块驱动设备初识)
  16. Xms Xmx PermSize MaxPermSize的含义
  17. 编译原理——程序编译的基本流程
  18. 象棋棋谱xqf工具包 v2.02 绿色
  19. 20181213股票复盘
  20. 沙拉翻译网页双语显示,程序员必备,是神器没错了

热门文章

  1. RUNOOB python练习题29
  2. 公司想申请网易企业电子邮箱,怎么样?
  3. 马约拉纳费米子:推动量子计算的“天使粒子”
  4. 添加dubbo xsd的支持
  5. iframe中的历史记录问题汇总及解决方案[转]
  6. advanced installer更换程序id_好程序员web前端培训分享kbone高级-事件系统
  7. 从早期的初创企业到MongoDB的经理(播客)
  8. 将json 填入表格_如何将Google表格用作JSON端点
  9. 心学 禅宗_禅宗宣言,用于有效的代码审查
  10. 阿里的技术愿景_技术技能的另一面:领域知识和长期愿景