实验3:LSB隐写分析

1. 实验类别

        设计型实验:MATLAB设计并实现基于视觉攻击和统计攻击的LSB隐写分析方法。

2. 实验目的

        理解LSB隐写分析的思想和方法,掌握基于视觉分析的LSB隐写分析方法,对LSB嵌入前后的载体图像进行分析。

        掌握基于卡方检验的LSB隐写分析方法,在不同嵌入率、嵌入位置、嵌入信息情况下,利用卡方检验进行隐写分析。

        能够独立编写上述两种隐写分析matlab程序。

3. 实验条件

  • Windows 2000或Windows Xp以上操作系统;
  • MATLAB 6.5以上版本软件;
  • 图像文件

4. 实验原理

点击查看         隐写分析技术是对表面正常的图像、音频、视频等载体信号(尤其是通过互联网进行传输的信号)进行检测,判断其中是否嵌有秘密信息(这些秘密信息是通过一定的隐写算法嵌入的),甚至只是指出媒体中存在秘密信息的可能性,这样可以找到敌对隐蔽通信的信源,从而阻断隐蔽通信的信道。

4.1 基于视觉攻击的LSB隐写分析

        视觉攻击是指利用人的视觉感知特性来判断载密图像异常变化。LSB替换选用最低位平面来嵌入秘密信息,最低位平面对图像的视觉效果影响最轻微。因此,可以从图像的最低有效位组成的图像中判断是否有隐藏消息。图像的LSB和最高位以及其他点有一定的关系,特别是对自然拍摄的BMP图像。但是在选择嵌入位置时,一般都同等对待载体中所有样本点,忽略了载体本身存在的空间相关性,就能够被观察出嵌入的痕迹。

4.2 基于卡方检验的LSB隐写分析

        chi-square分析又称卡方分析。普通图像像素值的分r布情况由于LSB嵌入会发生变化。使用LSB嵌入水印时,如果像素值最低位比特与水印比特相同,那么保留该像素值不做变化;否则,使用水印比特位代替像素值的最低比特位。例如,水印比特位为1时,若像素值为(128)D=(1000 0000)B,则将像素值变为(129)D=(1000 0001)B;若像素值为(17)D=(0001 0001)B,则不改变该像素值。         分析该处理过程,像素值会由2i变为2i+1,而不会变为2i-1;或者由2i+1变为2i,而不会变为2i+2。即像素值在值对2i和2i+1之间翻转。因此,若用hi表示像素值为i的像素个数,那么,使用LSB嵌入后,h2i和h2i+1会比较接近,远小于普通图像中h2i和h2i+1的距离。

5. 实验步骤

5.1 基于视觉攻击的LSB隐写分析

(1)对图像进行位平面分解:位平面是指依次取出每个像素点对应位的值组成一个位平面。一副灰度图像中每个像素点的灰度值可以由8个二进制来表示,因此可以分解成8个位平面。举例,假设图像有两个像素点,灰度值分别为1和3,其对应的二进制为分别为00000001和00000011,那么该图像分解成的8个位平面以此为00、00、00、00、00、00、01、11。每个位平面均为一个二值图,即像素点的值非0即1。bitplanek = bitget(A,k);获取A的第k位。

(2)分别抽取载密图像和原图像的最低位平面,进行对比lsbbitplanek = bitget(A,1); 获取A的第1位。

(3)在不同嵌入率10%、30%、50%、70%下进行分析对比。

步骤如下(以嵌入率为10%为例):

首先使用LSB算法对图片进行水印嵌入,如下图水印文字比特占比为$\frac{2656}{262144}$。

对原图像和10%嵌入率水印图像分别取最低位平面,进行视觉对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
% 视觉攻击
clc;clear;
img = imread('lena.bmp'); % 读入原图像
img_watermarked = imread('LSB_watermarked.bmp'); % 读入嵌入水印图像
img_R = img(:,:,1); % 为了得到正确的行高列宽,不取一个图层,则列数为512*3,下方循环会溢出。
[row,col] = size(img_R); % 获取图像行列宽
low_img = zeros(row,col); % 用于保存原图像的最低位平面
low_watermarked = zeros(row,col); % 用于保存嵌入水印图像的最低位平面
for outer=1:row
for inner=1:col
% 用bitget分别获取原图像和嵌入水印图像的最低比特位
low_img(inner,outer) = bitget(img(inner,outer),1);
low_watermarked(inner,outer) = bitget(img_watermarked(inner,outer),1);
end
end
figure('NumberTitle', 'off', 'Name', 'LSB视觉攻击');
subplot(1,3,1);imshow(low_img);title('原始图像');
subplot(1,3,2);imshow(low_watermarked);title('10%嵌入率的水印图像');
subplot(1,3,3);imshow(imsubtract(low_img,low_watermarked));title('两图像做差');

增加hidden.txt中的文字内容,分别更改嵌入率为30%,50%,70%,重复运行上述程序,可得:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
% 具体代码,与上方代码原理相同,只是添加多组数据
% 多组视觉攻击,提前保存了不同嵌入率的图像
clc;clear;
img = imread('lena.bmp');
img_watermarked_10 = imread('LSB_watermarked_10.bmp');
img_watermarked_30 = imread('LSB_watermarked_30.bmp');
img_watermarked_50 = imread('LSB_watermarked_50.bmp');
img_watermarked_70 = imread('LSB_watermarked_70.bmp');
img_R = img(:,:,1);
[row,col] = size(img_R);
low_img_0 = zeros(row,col);
low_watermarked_10 = zeros(row,col);
low_watermarked_30 = zeros(row,col);
low_watermarked_50 = zeros(row,col);
low_watermarked_70 = zeros(row,col);

for outer=1:row
for inner=1:col
low_img_0(inner,outer) = bitget(img(inner,outer),1);
low_watermarked_10(inner,outer) = bitget(img_watermarked_10(inner,outer),1);
low_watermarked_30(inner,outer) = bitget(img_watermarked_30(inner,outer),1);
low_watermarked_50(inner,outer) = bitget(img_watermarked_50(inner,outer),1);
low_watermarked_70(inner,outer) = bitget(img_watermarked_70(inner,outer),1);
end
end
figure('NumberTitle', 'off', 'Name', 'LSB视觉攻击');
subplot(2,5,1);imshow(low_img_0);title('0%原始图像');
subplot(2,5,2);imshow(low_watermarked_10);title('10%嵌入率的水印图像');
subplot(2,5,3);imshow(low_watermarked_30);title('30%嵌入率的水印图像');
subplot(2,5,4);imshow(low_watermarked_50);title('50%嵌入率的水印图像');
subplot(2,5,5);imshow(low_watermarked_70);title('70%嵌入率的水印图像');
subplot(2,5,7);imshow(imsubtract(low_img_0,low_watermarked_10));title('10%与原图做差');
subplot(2,5,8);imshow(imsubtract(low_img_0,low_watermarked_30));title('30%与原图做差');
subplot(2,5,9);imshow(imsubtract(low_img_0,low_watermarked_50));title('50%与原图做差');
subplot(2,5,10);imshow(imsubtract(low_img_0,low_watermarked_70));title('70%与原图做差');

5.2 基于卡方检验的LSB隐写分析

  1. 对原始图像和载密图像进行灰度直方图对比,选取部分像素值,观察$h_{2i}$和$h_{2i+1}$的在嵌入前和嵌入后的差值情况。n = hist(A(:), 0:255)';获取A的像素值分布,n为像素值统计矩阵,索引为像素值,值为该像素值的个数。stem(a:b,n(a+1:b+1));画出直方图,a:b为像素值区间。
  2. 对图像进行分区域卡方检测。依次取图像的部分比例区域,逐渐扩大,如从10%开始,每次加1%,直到100%。对这部分区域进行卡方检测,编写卡方检测函数,统计$h_{2i}$和$h_{2i+1}$,计算$h_{2i}^\star $,计算$x^2=\sum_{i=1}^{k}\frac{(h_{2i}-h_{2i}^\star)}{h_{2i}^\star }\sim x^2(k)$,计算自由度k下的密度函数,得到隐写概率p = chi2cdf(r,k-1);p为隐写概率,chi2cdf(r, k - 1)为卡方分布的概率密度函数,绘制分析区域比例和隐写概率曲线图。

  3. 在不同嵌入率0%、10%、30%、50%、70%下进行检测,分析检测的结果。

步骤如下

灰度直方图对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
% 以嵌入率50%为例
clc;clear;
figure('NumberTitle', 'off', 'Name', 'LSB隐写分析:灰度直方图');
img = imread('lena.bmp'); % 读入原图像
img_watermarked_50 = imread('LSB_watermarked_50.bmp'); % 读入嵌入水印图像
a = 100;b = 120; % 像素值区间
img_R = img(:,:,1);
% 获取像素值分布,n为像素值统计矩阵,索引为像素值,值为该像素值的个数
n_1 = hist(img_R(:), 0:255);
subplot(1,2,1);stem(a:b,n_1(a+1:b+1));title("原始图像灰度直方图");
img_watermarked_R = img_watermarked_50(:,:,1);
n_2 = hist(img_watermarked_R(:), 0:255);
subplot(1,2,2);stem(a:b,n_2(a+1:b+1));title("载密图像灰度直方图");

卡方分布的概率密度函数,写在单独的.m文件中,后续程序直接引用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
% 卡方分布的概率密度函数
function p = LsbPrb(x)
sz = size(x);
% 图像0-255像素数量的直方图
n = hist(x(:),0:255);
T = 1;start = 1;
% 统计相邻两像素之间个数,因此步长为2
hi1 = n((start:2:255));
hi2 = n((start+1:2:256));
his = (hi1+hi2)/2;
% 找出并存入his大于1的数值
rows = find(his>=T);
% 如果his无大于1,则说明不存在隐写
if isempty(rows)
p = 0;
return;
end
k = length(rows);
% 根据公式求隐写概率
r = sum(((hi1(rows)-his(rows)).^2)./(his(rows)));
% p为隐写概率,chi2cdf(r, k - 1)为卡方分布的概率密度函数
p = 1-chi2cdf(r,k-1);

卡方分析主程序代码(老师演示版本):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
% 老师演示的代码
% 其中既包括了加入水印的过程,也包括卡方分析
clc;clear;
img = imread('lena.bmp');
sz = size(img);
for k =1:11
rt = double(k-1)/10;
row = round(sz(1)*rt);
fprintf(1,'rt:%d\n',row);
col = sz(2);
% 生成一个row * col的矩阵,其中元素仅有0,1且概率为0.5
m1 = randsrc(row,col,[0 1;0.5 0.5]);
stg = img;
stg(1:row,1:col) = bitset(stg(1:row,1:col),1,m1);
imwrite(stg,sprintf('stg_%d.bmp',floor(100*rt)));
i = 1;
for rto = 0.1:0.01:1
row = round(sz(1) * rto);
col = sz(2);
p(k,i) = LsbPrb(stg(1:row,1:col));
i = i+1;
end
end
x = round([0.1:0.01:1]*sz(1))/sz(1)*100;
figure('NumberTitle', 'off', 'Name', 'LSB隐写分析:chi-square分析');
plot(x,p(1,:),'k-',x,p(2,:),'r-',x,p(3,:),'b--',x,p(4,:),'g--',x,p(5,:),'c--',x,p(8,:),'y--');axis([10 100 0 1.2]);
legend('0%','10%','20%','30%','40%','70%');
xlabel('Size of sample(%)');ylabel('Probability of embedding');

对于实验2中LSB嵌入算法得到的10%,30%,50%,70%的水印图像进行分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
clc;clear;
j = 1;
% 因为水印嵌入率为10,30,50,70,所以k的遍历步长如此设置,利于读入图像
for k = -10:20:70
% 读入载密图像,-10时候读入原图像
if k == -10
stg = imread('lena.bmp');
sz = size(stg); % 返回行,列,面
fprintf('LSB_watermarked_0.bmp\n');
else
stg = imread(['LSB_watermarked_',num2str(k,'%d'),'.bmp']);
fprintf(['LSB_watermarked_',num2str(k,'%d'),'.bmp\n'])
end
i = 1;
% 依次取图像的部分比例区域,逐渐扩大,如从10%开始,每次加1%,直到100%
for rto = 0.1:0.01:1
% 获取部分区域的行,列
row = sz(1);
col = round(sz(2) * rto);
% 引用LsbPrb函数,返回值为隐写概率p
p(j,i) = LsbPrb(stg(1:row,1:col));
i = i+1;
end
j = j+1;
end

x = round([0.1:0.01:1]*sz(1))/sz(1)*100;
figure('NumberTitle', 'off', 'Name', 'LSB隐写分析:chi-square分析'); % 绘图
plot(x,p(1,:),'k-',x,p(2,:),'r-',x,p(3,:),'b--',x,p(4,:),'g--',x,p(5,:),'c--');axis([10 100 0 1.2]);
legend('0%','10%','30%','50%','70%'); % 图例
xlabel('Size of sample(%)');ylabel('Probability of embedding'); % 轴注

结果如下图,但存在一定的偏差,如原图10%区域上时可能存在嵌入率,30%,50%,70%嵌入率与占比率不匹配,代码检查好几遍原理是对的上的,由LSB隐写分析实验中嵌入不同信息的比较(伪随机序列和文本二进制序列对比)可知与老师实验中图片结果相比曲线区别较大的原因为:文本文件不是随机的,由人类语言的特点决定

6. 实验报告

1.理解整个隐写分析的过程,试写出实验的关键步骤。简单概述你在编程过程中遇到了哪些问题,如何解决的?

  • 实验内容及步骤如上所示。
  • 卡方检测:在之前LSB嵌入实验中的图像水印嵌入顺序为列嵌入(视觉攻击可见),而老师演示的代码为行嵌入,因此卡方分析时需要固定行数不变,逐渐扩宽列数。
  • 卡方测试生成的图像中嵌入率与占比率不相符。查询资料。

2.通过对lsb的视觉攻击和卡方检测分析,总结这两种方法的优缺点。试分析如何改进lsb方法,能够抵抗视觉攻击和卡方检测。

视觉攻击:

        对LSB最后一个为平面提取的视觉攻击可以很清楚从图像中看出明显的横条,即嵌入区域。但是在对随机嵌入进行攻击时,还需要对其与原图进行做差才能看出,在仅有嵌入后图像的情况下是不能通过视觉攻击分析出是否嵌入了内容,如下图:

        另外视觉攻击对于人的主观依赖性较强,可靠性难以保证;并且自动化能力弱,不适用于大批量载体检测。

卡方检测:

        卡方分析能够对隐写率做出分析,并且能判断嵌入的位置。但是嵌入率较低,或者采取嵌入位置随机分布,则难以通过LSB嵌入后临近像素值个数的相近的特点进行分析。

LSB改进:

        采用随机嵌入的方式可以降低视觉攻击的威胁,并且因为随机嵌入打乱了文本语言的规律性,从而也可让卡方分析的结果有一定失真。

7. 可选实验(尚未订正)

  1. 不同嵌入位置的对比检测,对lsb随机嵌入进行视觉攻击分析和卡方检测。

    视觉攻击:在上文代码中做些修改,加入对随机嵌入图像的攻击,同时选用的均为30%有效文本嵌入。

    卡方检测:在上文代码中做些修改,加入对随机嵌入图像的检测,同时选用的均为30%有效文本嵌入。

  2. 试利用RS分析方法对lsb进行隐写分析。

            解压老师发的压缩包,运行compute_plot可以得到以下结果,(挖坑)有时间再给源码加上注释发出来。。。

鸣谢❀参考大佬文章