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