天天看點

平安夜的祝福

本來想等文章收錄之後再發表到這裡的,然而一直沒有等到,不知道為什麼;寫于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

平安夜的祝福

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 以後再寫吧……

哈哈,是不是又發現了一片新大陸!