TAT.Johnny 不能说的秘密——前端也能玩的图片隐写术
In 未分类 on 2016年03月24日 by view: 59,583
29

上个月在千里码刷题的时候,碰到了比较有意思的一道题—— 隐写术。既然感觉有意思,又很久没有玩过 canvas,所以今天结合这两块内容带大家探索一下。

隐写术算是一种加密技术,权威的 wiki 说法是“ 隐写术是一门关于信息隐藏的技巧与科学,所谓信息隐藏指的是不让除预期的接收者之外的任何人知晓信息的传递事件或者信息的内容。” 这看似高大上的定义,并不是近代新诞生的技术,早在 13 世纪末德国人 Trithemius 就写出了《隐写术》的著作,学过密码学的同学可能知道。好了,说了这么多,隐写术到底是什么技术,让我们看一个例子。

下面是一张看似普通的图片,但其中却藏有另一个肉眼无法识别的图像哦。

这是如果把上图每个色彩空间和数字 3 进行逻辑与运算,再把亮度增强 85 倍,可以得到下图。

简单的说,上述的处理过程可以理解为对图片像素的处理,也就是说,加密的信息散布在每个像素点上。可是,13 世纪还没有“ 像素” 这个概念吧?!没错,上面这个例子只是隐写术的一个现代技术实现,隐藏信息的手段有很多,我们日常的钞票防伪也算是隐写术的一种,所以标题上也限定了我们的讨论范围—— 图片隐写术。

{15AAFDB9-59F0-458E-93EF-AE4E799FA5D2}

(电子水印与隐写术有一些共通点)

聚焦到载体为图片的隐写术,一起来从前端角度分析其技术原理。

我们知道图片的像素信息里存储着 RGB 的色值,R、G、B 分别为该像素的红、绿、蓝通道,每个通道的分量值范围在 0~255,16 进制则是 00~FF。在 CSS 中经常使用其 16 进制形式,比如指定博客头部背景色为 #A9D5F4。其中 R(红色)的 16 进制值为 A9,换算成十进制为 169。这时候,对 R 分量的值+1,即为 170,整个像素 RGB 值为 #AAD5F4,别说你看不出差别,就连火眼金金的“ 像素眼” 设计师都察觉不出来呢。于此同时,修改 G、B 的分量值,也是我们无法察觉的。因此可以得出重要结论:RGB 分量值的小量变动,是肉眼无法分辨的,不影响对图片的识别。

有了这个结论,那就给我们了利用空间,常用手段的就是对二进制最低位进行操作,下面就用 canvas 来演示一下。

解开图中的秘密

这是一张我们当家美女小兰师姐的照片,为了让例子足够简单,里面的 R 通道分量被我加入了文本信息,想知道其中的信息,可以跟我用 canvas 代码来解开。

首先在页面加入一个 canvas 标签,并获取到其上下文。

接着将图片先绘制在画布上,然后获取其像素数据。

打印出数据,会看到有一个非常大的数组。

 

QQ截图20160325174947

这个一维数组存储了所有的像素信息,一共有 256 * 256 * 4 = 262144 个值。其中 4 个值一组,为什么呢?在浏览器中解析图片,除了 RGB 值外,每组第 4 个值为透明度值,即像素信息实际为大家熟知的 rgba 值。 

这里的解密规则是对 R 通道进行处理,R 的分量最低位为 1 则该像素设为红色,R 的分量最低位为 0 则该像素设为黑色,直接看代码实现,完成后我们再绘制到 canvas,即可看到结果。