一個像素就是 8 個位元
灰階影像的每個像素是 0 到 255 的整數,也就是 8 個位元。每個位元代表的份量不同:最左邊的 bit 7 值 128,最右邊的 bit 0 只值 1。
試著翻轉不同的位元。翻 bit 7,亮度整個跳掉一半;翻 bit 0,數值只差 1,眼睛根本看不出來。這個「最低有效位元」(Least Significant Bit,LSB)就是藏東西的地方。
從一個像素開始,一步一步看懂 LSB 影像隱藏:怎麼藏、藏完差多少、怎麼加密,以及它會在哪裡被識破。每一段都附一個可以直接操作的小工具。
灰階影像的每個像素是 0 到 255 的整數,也就是 8 個位元。每個位元代表的份量不同:最左邊的 bit 7 值 128,最右邊的 bit 0 只值 1。
試著翻轉不同的位元。翻 bit 7,亮度整個跳掉一半;翻 bit 0,數值只差 1,眼睛根本看不出來。這個「最低有效位元」(Least Significant Bit,LSB)就是藏東西的地方。
把整張影像所有像素的同一個位元抽出來,會得到一張只有黑白的「位元平面」。bit 7 平面幾乎就是影像的輪廓,越往下越像雜訊。到了 bit 0,原本的影像已經看不出來了。
最上面那張圖旁的 bit 7 到 bit 0 按鈕,就是在看這 8 張平面。正因為 bit 0 本來就像雜訊,換成別的內容也不會有人察覺。
先把秘密影像轉成黑白,每個像素就只剩 0 或 1。接著把載體每個像素的 bit 0 清掉,再填入對應的秘密位元:
要取出秘密,只要把藏密影像每個像素和 1 做 AND,也就是 s = p′ AND 1。
工具裡是從影像中隨機挑的 8×8 小區塊。秘密位元剛好等於原本的 bit 0 時,像素完全不變;不一樣時才改動,而且只差 1。
衡量藏密影像和原圖差多少,最常用的是均方誤差 MSE 和峰值訊噪比 PSNR:
LSB 法大約一半的像素要改、每次只差 1,所以 MSE ≈ 0.5,PSNR ≈ 51.14 dB。一般認為 PSNR 超過 30 dB,肉眼就很難分辨。
如果改藏在第 k 個位元,每次改動變成 2ᵏ,MSE 變成 0.5 × 4ᵏ,PSNR 每往上一層就掉約 6 dB。長條圖是用這張圖實際算出來的結果。
只用 LSB 藏,任何人把 bit 0 平面抽出來就看得到秘密。所以可以先用 Arnold 轉換(Arnold's cat map)把秘密影像的像素位置打亂:
這個矩陣的行列式是 1,所以轉換一定可逆。更神奇的是,重複做固定次數之後影像會自己變回原樣。256×256 的影像,這個週期是 — 次。
做幾次就是金鑰。知道次數的人可以反轉回來;不知道的人只會看到雜訊。置亂只換位置不換數量,所以完全不影響 PSNR。
視覺攻擊:直接看 bit 0 平面。沒加密的秘密一眼就被看穿,置亂過的則像雜訊。
卡方攻擊:LSB 替換只會讓 2i 和 2i+1 這兩個數值互相轉換(例如 100 ↔ 101),當秘密位元是 0、1 各半的亂數時,每一對數值的出現次數會被「拉平」。卡方檢定專門偵測這種現象。
反直覺的是:把秘密加密成均勻亂數,反而最容易被卡方攻擊抓到。改用 ±1 匹配(不同時隨機 +1 或 −1,而不是只翻 bit 0)就不會產生這種成對的痕跡。
LSB 法把資訊放在最脆弱的地方。JPEG 壓縮會把影像轉到頻率域、捨棄細節再轉回來,每個像素的值都會被改動一點點,bit 0 幾乎全部重洗。
拉動 JPEG 品質滑桿試試。就算品質設到 95,取出的秘密也已經接近亂碼(BER 接近 0.5 就等於亂猜)。所以藏密影像只能用 PNG、BMP 這類無損格式傳送;想要抗壓縮,就得改用 DCT、DWT 等頻率域的隱藏方法。
把上面所有原理接成一條完整流程。換成你自己的兩張圖、改任何一個參數,六個步驟和數值都會馬上更新。圖片不會上傳到任何地方。