戴兜

戴兜

Coding the world.
github
bilibili
twitter

base64数据隐写实现原理分析

image

在开始这篇文章前,先让我们来看一组 base64 编码的字符串

ZG==
YY==
aW==
ZF==
cm==
aM==
b2==
dc==
c2==
Zf==

解码后的内容是 daidrhouse,似乎没有什么问题。但是仔细看,第一行和第 4 行解码后的结果都是 d,但内容竟然不太一样?

按照正常的 base64 编码,daidrhouse 应该得到下面的结果。

ZA==
YQ==
aQ==
ZA==
cg==
aA==
bw==
dQ==
cw==
ZQ==

显然,与前者相比,每串 base64 的第二个字符都被改变了,但解码后的内容依然不变,这得从 base64 编码的原理说起。

什么是 base64

顾名思义,base64 编码就是用 64 个 ascii 字符作为基础来编码二进制内容的一种编码方式。相信各位一定在网页中看到过 base64 编码的内嵌图片,甚至 QQ 音乐传输歌词文件时,也采用了 base64 编码。将二进制编码为 ascii 字符,使数据在某些场景下更便于阅读、便于传输。当然,将所有二进制「浓缩」到区区 64 个字符来表示,一定会在体积上作出妥协。字符在编码完成后,会增大 1/3 倍,至于原因,下面会讲到。

索引表

base64 有一张标准编码表,为 64 个 ascii 字符排序并赋予索引。

索引字符索引字符索引字符索引字符
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/

有时为了防止混淆(比如链接),会使用 . _ 来代替索引表中的 + /

编码方式

base64 将 3 个字节(24 位)作为一组进行处理。不足 3 字节时填充 0,并在结尾使用 = 来标识填充的字节数。并将每 6 位作为 1 小组,将 24 位编码成 4 组 6 位二进制。此时,这 6 位二进制一共有 26=642^6=6426=64 种情况,正好能够用 64 个字符来表示。(这也解释了为什么编码完成后体积会增大 1/3)

举些栗子

image

image

隐写的原理

base64 在解码的时候,会按照字符串末尾的 = 数量来删除相应字节数。或许你已经发现了,当一组字符的数量为 1 字节或 2 字节的时候,会有 4 位或 2 位二进制在解码时被忽略,及下图的红色标识。

image

image

红色标识的这些二进制,能够被编码,但解码时却会被忽略。修改这些位置的内容,不会影响到原始数据。

解决问题

现在,可以来尝试解决文章开头的问题了。那组 base64 编码的字符串,隐藏了什么?

image

image

image

image

image

image

image

image

image

image

将所有红色标识的二进制位拼接起来,可以得到最后的结果 hello

image

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.