隐写术:在其他事物中隐藏事物的艺术与科学 - 第二部分
第二部分:在图像中隐藏数据
Dakota Nelson* //
在第一部分中,我们讨论了比特如何构成图像,以及这对我们的数字捉迷藏游戏意味着什么。在这篇文章中,我们将利用新的藏身之处,开始隐藏东西,就像人们常做的那样。
既然我们知道在哪里隐藏,我们如何实际利用这些知识呢?当然是通过编程!
首先,我们需要一些东西来隐藏。我将把更可疑的部分留给你,只使用这段Python代码片段,它将获取一些文本并将其转换为比特列表:
|
|
这段代码的最终输出应该是一个看起来像这样的消息:
|
|
这是短语“this is a message”的二进制形式。哇!我们有东西要隐藏了!
现在我们必须获取这张图片:
并将我们的消息放入其中,将其隐藏在图像的最低有效位中。
我们将使用这段代码片段,它打开一个现有图像并向其中添加消息,将消息中的每个比特重复九次,原因稍后会变得清楚:
|
|
你可能想知道……为什么我们要如此重复消息?每个比特重复九次似乎过分了。
事实证明,我们并不是唯一注意到图像中最低有效位基本上是随机的人。有人已经抢先一步进入了我们的藏身之处,并且他们正在用它来做无聊的事情。
根据维基百科,压缩的目标是“减少图像数据的无关性和冗余性,以便能够以高效的形式存储或传输数据。”
但那些“无关和冗余的数据”正是我们想要放置我们狡猾消息内容的地方,而压缩会破坏这些比特。该死。事实证明,如果存在无用的比特,比如每个像素值的最低有效位,它们非常适合隐藏东西,因为没有人关心它们,但也是第一个被压缩丢弃的……因为没有人关心它们。
所以我们反击,通过大量重复自己,这样即使一些比特被压缩翻转,我们的数据仍然大部分能够通过。这不优雅,但有效。(这将在第三部分中更好地解释,我们将使用一些很酷的数学方法进入更优雅的方法。)
一旦我们通过代码运行图像,它看起来像这样:
这可能看起来很熟悉 - 现在我们知道这只小狗从第一部分隐藏的消息了!但是……一旦它被放进去,我们如何把它取出来呢?
方法如下:
|
|
在图像上运行这个,你得到原始消息和新提取消息的前20个字符:
|
|
太棒了!它们是一样的!我们刚刚使用隐写术在图像中隐藏了数据!(自己尝试一下:你能通过反转之前的过程将这些比特重新组装成文本吗?)
能够从图像中提取隐写编码的数据很酷,但必须如此重复自己意味着我们不能移动很多数据,而且它相当明显 - 带有隐藏数据的图像与原始图像看起来足够不同,如果你仔细观察,你可以看出有些不对劲。这张图像是500乘500像素,这意味着(因为我们只能每个像素隐藏一个数据比特)我们只能在这张图像中隐藏刚刚超过31 kB的数据。这很好,也有些用处,但你需要很多图片来发送任何重要数量的数据 - 特别是因为我们使用的是图像中最低有效的3位,而我们更愿意使用更少,这样图像看起来就不会有任何不同。在第三部分中,我们将探索如何使用更复杂的纠错代码使我们的数据隐藏更高效。
特别感谢Zoher Ghadyali和Philip Seger多年前合作编写了这些代码片段的原始版本。
*Dakota运营Striker Security - 你可以在https://strikersecurity.com/blog找到更多他的文章
评论
Mike - 2016年11月2日 @ 10:24 am
问题……如果我对你的系统进行取证分析,并且我遇到了原始图片和修改后的图片,我能否通过简单地查看哈希值来判断它被修改了?
Dakota - 2016年11月2日 @ 11:12 am
是的!隐藏数据会改变图像的哈希值。这是我在系统上比较image.bmp(普通图像)和image_steg.bmp(包含隐藏数据)时得到的结果:
|
|
当然,这需要你有一个原始图像进行比较。图像压缩、裁剪、任何其他编辑等也会改变哈希值,所以仅仅因为两个视觉上相似的图像有不同的哈希值并不一定意味着数据隐藏在一个中……但可能是。 🙂