本来想等文章收录之后再发表到这里的,然而一直没有等到,不知道为什么;写于2016年12月25日。


昨天是平安夜,收到了好多祝福,还有班长大大Apple(!phone)

BUT,我能直接看懂祝福的内容,这样好没有挑战性哦。


想把自己的祝福隐藏在什么里面,然后发给想要告诉的人,毕竟我是计算机系的学生啦!


可是放在哪里好呢?

  1. 加密成字串
  • 可以直接被破译的有base64,可是看起来好简单
  • 自己写的话在大一就已经做过了,不想重复
  • 其他的,或许很难破解咯
  1. 隐藏在图片里面
  • 以前没有做过的事情,可以尝试
  • 会让对方想到文字就在图片里面的陷阱


接下来就给大家说两种简单的隐写方法吧

0x00 图种

因为一张正常的jpg图片是以​​FF D9​​作为结束标志的,而图片查看器在打开图片的时候会忽略结束符之后的内容,因此,我们可以在图片的结束符之后追加我们自己想要隐藏的信息。

平安夜的祝福_图片查看器


我们需要制作一个zip文件,放入想要隐藏的内容,再找一张jpg格式的图片,以二进制方式把两个文件首尾相接即可。

Windows :​​copy /b photo.jpg+file.zip output.jpg​

Linux :​​cat file.zip >> photo.jpg​

缺点是这样的方式隐藏的信息很容易被发现,因为只需要看看jpg图片的​​FF D9​​之后有没有内容便可知道真相。


0x01 平安夜的惊喜

public.png

平安夜的祝福_图片查看器_02

key.png

平安夜的祝福_python_03

key.png是原图,我在它里面添加了自己想要说的话,然后public.png是处理之后的图片,你能在其中找到答案么?


还有的就是,我把它发给了我最最最最最要好的朋友[害羞]:

>> 呐,这两个 [可爱]
<< 这两个有什么区别 [小纠结]
>> 不告诉你
<< [doge]
>> 里面有一段很重要的信息 [可爱]
<< 要我自己发现吗
<< 还是以后再告诉我
>> 自己发现咯
>> 不过晚上24:00之前会给你答案的
>> 在此之前,就看你咯 [可爱]


不过在这里,千千再给大家透露一张图,是public.png经过某种处理之后的图片

平安夜的祝福_图片查看器_04

>> 要我告诉你答案嘛
<< 这哪能看出来
<< [doge]
>> 我可没让你看
>> [白眼]
<< 看了都看不出来,不看更不知道了
>> [托腮]
<< so


So,揭晓答案的时候到了。

图片的每个像素点一般是由三种颜色组成(红绿蓝三原色),而每种颜色储存使用了​​8bit​​​,而我们修改这​​8bit​​的最低位,最多只会对原来的数值影响1,也就是影响最小的一位,毕竟我们要最大程度保留图片的可视性对吧!

平安夜的祝福_像素点_05

修改颜色的最低位,这样微小的差距,在人眼看来是看不出来区别的,这样我们就可以使用这最低的一位来储存我们自己的信息啦!

平安夜的祝福_像素点_06


我的做法

因为我是把一张图片隐藏到了另一张图片里面了,可是空出来的1位我们如何来存储同样大小的另一张图片呢?

这里前提是两张图片同样大小,也就是同样多的像素点,对于这种情况,图像的点阵如果不是稀疏矩阵的话我们就只能舍弃精度啦!

首先求出整个图片的所有像素点颜色值的平均值,然后对于每一个点的颜色,大于平均值的设为1,其余设为0,这样处理的话,原本八位的信息便压缩成了1位,也就只有两种信号咯,解码的时候可以黑白显示。

加密
#! /usr/bin/env python3

from PIL import Image
import numpy as np


# 处理原图
def dealsrc(filename):
arr = np.array(Image.open(filename))
arr[arr[:, :, 0] == 255] -= 1
return arr


# 处理需要隐藏的图片
def dealmsg(filename):
# 打开图片并转换成8位像素黑白图的数组
arr = np.array(Image.open(filename).convert('L'))
# 计算均值
limit = arr.mean()
arr[arr[:] < limit] = 0
arr[arr[:] >= limit] = 1
return arr


# 生成隐写图片
def makeshdf(srcname, msgname):
key_array = dealsrc(srcname)
pass_array = dealmsg(msgname)
key_array[:, :, 0] += pass_array
img = Image.fromarray(key_array)
img.save('public.png')


if __name__ == '__main__':
makeshdf('../key.png', '../pass.png')


解密
#! /usr/bin/env python3

from PIL import Image
import numpy as np


# 处理原图
def dealsrc(filename):
arr = np.array(Image.open(filename))
arr[arr[:, :, 0] == 255] -= 1
return arr


# 生成隐写图片
def makemsgf(srcname, shdname):
key_array = dealsrc(srcname)
public_array = np.array(Image.open(shdname))
ans_array = (public_array[:, :, 0] - key_array[:, :, 0]) * 255
img = Image.fromarray(ans_array)
img.save('solve.png')


if __name__ == '__main__':
makemsgf('../key.png', '../public.png')


怎么说呢?

使用的信息载体最好是无损压缩的图片格式,png就是这样的格式,而jpg格式属于有损压缩,用它储存信息的话可能会在压缩过程中破坏。

因为之前说过这样的隐藏会损失图片精度,所以解密出来的图片也就只能是黑白格式的咯!


原图

平安夜的祝福_python_07

解密之后的图片

平安夜的祝福_像素点_08


0x03 以后再写吧……


哈哈,是不是又发现了一片新大陆!


未知的秘密,未知的人儿

我啊,只要有一个人便足够了,能传达得到吗,如果能就好了……