LSB 隱寫術

曾幾何時,我寫下了我的 集線器上的第一篇文章。 這篇文章致力於解決一個非常有趣的問題,即隱寫術。 當然,那個老話題中提出的解決方案不能稱為真正意義上的隱寫術。 這只是一個帶有文件格式的遊戲,但仍然是一個非常有趣的遊戲。

今天我們將嘗試更深入地研究 LSB 演算法。 如果您有興趣,歡迎您下貓。 (削減下的是流量:大約一兆位元組。)

首先有必要做一個簡單的介紹。 大家都知道,密碼學的目的是要讓秘密資訊無法被讀取。 當然,密碼學有其應用,但還有另一種資料保護方法。 我們不必加密訊息,但假裝我們沒有它。 這正是發明隱寫術的原因。 維基百科向我們保證「隱寫術(來自希臘語 στεγανοσ - 隱藏和希臘語 γραφω - 我寫的,字面意思是「秘密寫作」)是透過對傳輸事實保密來隱藏訊息傳輸的科學。

當然,沒有人禁止將密碼學和隱寫術方法結合。 而且,在實踐中他們是這樣做的,但我們的任務是了解基礎知識。 如果你仔細研究維基百科的文章,你會發現隱寫演算法包含所謂的。 容器和訊息。 容器是任何有助於隱藏我們的秘密訊息的資訊。

在我們的例子中,容器將是 BMP 格式的映像。 首先,我們來看看這個文件的結構。 檔案可分為4部分:文件頭、圖像頭、調色盤和圖像本身。 出於我們的目的,我們只需要知道標頭中寫入的內容。

標頭的前兩個位元組是BM 簽名,然後用雙字寫入檔案大小(以位元組為單位),接下來的4 個位元組保留且必須包含零,最後另一個雙字包含距檔案開頭的偏移量。檔案到影像的實際位元組。 在 24 位元 bmp 檔案中,每個像素都使用三個 BGR 位元組進行編碼。

現在我們知道如何獲取圖像,剩下的就是了解如何在那裡寫入我們需要的資訊。 為此,我們需要 LSB 方法。 此方法的本質如下:我們替換負責顏色編碼的位元組中的最低有效位元。 假設我們的秘密訊息的下一個位元組是 11001011,並且圖像中的位元組是...11101100 01001110 01111100 0101100111...,那麼編碼將如下所示。 我們將秘密訊息位元組分成 4 個兩位部分:11、00、10、11,並用結果片段取代圖像的低位元:...11101111 01001100 01111110 0101100111…. 這種替換通常是人眼無法察覺的。 此外,許多較舊的輸出設備甚至無法顯示如此小的變化。

顯然,您不僅可以更改 2 個最低有效位,還可以更改任意數量的位。 有以下模式:我們改變的位數越多,我們可以隱藏的訊息就越多,這對原始影像造成的干擾就越大。 例如,這裡有兩個圖像:

LSB 隱寫術
LSB 隱寫術

儘管我盡了最大努力,我還是看不出它們之間的區別,但儘管如此,在第二張圖像中,使用所描述的方法,劉易斯·卡羅爾的詩《狩獵蛇》被隱藏了。 如果您已經讀到這裡,那麼您可能有興趣了解其實現。 這很簡單,但我會立即警告您,一切都是在 Delphi 中完成的。 這樣做的原因有二:1.我認為Delphi是一門很好的語言;2.我認為Delphi是一種很好的語言。 XNUMX. 這個程式是在準備電腦視覺基礎課程的過程中誕生的,而我教授這門課程的人除了 Delphi 之外還不懂任何東西。 對於不熟悉文法的人,需要解釋一件事:shl x 是位元左移 x,shr x 是位元右移 x。

我們假設我們正在將儲存在字串中的文字寫入容器並替換較低的兩個位元組:
錄音代碼:

對於 i:=1 到 length(str) 做
    開始
      l1:=位元組(str[i]) shr 6;
      l2:=byte(str[i]) shl 2; l2:=l2 shr 6;
      l3:=byte(str[i]) shl 4; l3:=l3 shr 6;
      l4:=byte(str[i]) shl 6; l4:=l4 shr 6;
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l1;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l2;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l3;
      f.WriteBuffer(tmp,1);
 
      f.ReadBuffer(tmp,1);
      f.Position:=f.Position-1;
      tmp:=((tmp shr 2) shl 2)+l4;
      f.WriteBuffer(tmp,1);
 
    結束;

閱讀代碼:

對於 i:=1 到 MsgSize 執行
    開始
      f.ReadBuffer(tmp,1);
      l1:=tmp shl 6;
      f.ReadBuffer(tmp,1);
      l2:=tmp shl 6; l2:=l2 shr 2;
      f.ReadBuffer(tmp,1);
      l3:=tmp shl 6; l3:=l3 shr 4;
      f.ReadBuffer(tmp,1);
      l4:=tmp shl 6; l4:=l4 shr 6;
      str:=str+char(l1+l2+l3+l4);
    結束;

好吧,對於那些真正懶惰的人來說—— 連結到程式及其原始碼.

謝謝。

來源: www.habr.com

添加評論