平安夜的祝福

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

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

 

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

 

可是放在哪里好呢?

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

 

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

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

key.png

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

 

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

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

 

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

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

 

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

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

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

我的做法

因为我是把一张图片隐藏到了另一张图片里面了,可是空出来的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格式属于有损压缩,用它储存信息的话可能会在压缩过程中破坏。

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

 

原图

解密之后的图片

 

0x03 以后再写吧……


哈哈,是不是又发现了一片新大陆!
 
未知的秘密,未知的人儿

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


  • 26 只已被捕捉
    • 邱雷 Chrome | 41.0.2272.101 Windows 7

      太会玩了,传说中的大佬!!!!!!!!!

      • 千千 Chrome | 41.0.2272.101 Windows 7

        呀!只是碰巧尝试了一下,哈哈