利用MATLAB实现WAV音频的LSB信息隐藏

0. 背景

音频信息隐藏技术就是将秘密数据直接嵌入音频载体中,但不影响原载体的使用价值,也不容易被人的知觉系统觉察或注意到。

音频信息隐藏技术作为信息隐藏技术的一个重要分支,受到越来越多的关注。

近年来,虽然数字音频信息隐藏技术的研究工作发展很快,出现了一些代表算法,但是与图像信息隐藏算法相比,数字音频信息隐藏技术面临着更大的挑战,因为人类听觉系统对随机噪声十分敏感,使得可以嵌入的数据量非常有限。

为了能够简明扼要地对音频信息隐藏技术进行说明,本文对WAV音频的LSB这种时域信息隐藏算法进行了研究。

1. LSB算法原理简介

LSB全称为:Least Significant Bit,即最不重要位。LSB方法是一种最简单的数据嵌入方法。任何秘密数据都可以看做是一串二进制位流,而音频文件的每一个采样数据也是用二进制数来表示的。这样,可以将每一个采样值的最不重要位(大多数情况下为最低位),用代表秘密数据的二进制位替换,以达到在音频信号中编码进秘密数据的目的。
下图即为利用LSB算法进行信息隐藏的过程。

在这里插入图片描述

提取隐藏的信息时的过程图如下图所示。
在这里插入图片描述
由图可知,如果有人截获了含有隐藏信息的音频采样数据,并且此人知道这段音频里藏有信息,且他知道被替换位为最低位,那么这个人就破解了这个秘密数据了。
因此对于LSB算法来说,密钥就是秘密数据的替换位的位置信息,如果想加大对秘密数据攻击的难度,可以用一段伪随机序列来控制嵌入秘密二进制位的位置。那么这段伪随机序列就可以作为密钥了。

2. 信息隐藏代码实现(随机序列)

下面,为了简化代码,易于读者理解,秘密数据采取的是一串随机生成的序列,并且采用的是二进制的最低位替换方法。

clc;
clear;
fid = fopen('music_new.wav', 'r');
oa = fread(fid, inf, 'uint8');
fclose(fid);

n = length(oa) - 44;
d = randsrc(1, n, [1 0]);
M = oa;
for i = 45 : 45 + n - 1  
    M(i) = bitset(M(i), 1, d(i - 44));
end

fid = fopen('music_new_secret.wav', 'wb');
fwrite(fid, M, 'uint8');
fclose(fid);

figure;
[y1,Fs] = audioread('music_new.wav');
x1 = (0:length(y1) - 1)/Fs;
subplot(2, 1, 1);
plot(x1, y1);
axis([0 max(x1) -1 1]);
xlabel('Time / (s)');ylabel('Amplitude');title('original audio');

[y2,Fs] = audioread('music_new_secret.wav');
x2 = (0:length(y2)-1)/Fs;
subplot(2, 1, 2);
plot(x2, y2);
axis([0 max(x2) -1 1]);
xlabel('Time / (s)');ylabel('Amplitude');title('information hiding audio');


figure;
subplot(2, 1, 1); plot(x1, y1); axis([0 0.6 -0.05 0.05]);
xlabel('Time / (s)');ylabel('Amplitude');title('original audio');

subplot(2, 1, 2); plot(x2, y2); axis([0 0.6 -0.05 0.05]);
xlabel('Time / (s)');ylabel('Amplitude');title('information hiding audio');
  • 这里解释一下第7行代码,为什么要减去44,同时也是解释了第10行代码,为什么要从45开始。
    因为我们是在wav格式的音频文件中进行信息隐藏,而wav格式的音频文件中,从文件头到数据前面一共有44字节的文件格式说明,因此在进行信息隐藏时,要跳过这44位。

  • 再解释一下第8行代码。第8行代码采用了MATLAB的生成指定范围的随机数函数,生成的随机数是1行n列的行向量,这个行向量的内容只有0和1。即,随机生成的这个向量d就是用来模拟一段秘密数据。

  • 第7行到第12行代码就是LSB算法的实现。首先第7行定义秘密数据的长度(这里取了能加密的最长的长度)。第8行生成了秘密数据d。第9行将原始音频的采样数据oa赋值给M,利用M存储含有隐藏信息的音频采样数据。第10行到第12行的代码,利用bitset函数,将M从第45个元素开始的每一位的最低位用秘密数据d的对应位替换掉,完成秘密数据的隐藏。

在给出程序运行图之前,需要说明的是,这个音频是一首歌曲的前奏,并且,我们给的秘密信息的长度遍布了整个时域。对于这个时长为29秒的音频,它最多能够存储的秘密信息长度是2557800bit,换算后为319725Byte,约等于312KB。
在这里插入图片描述
下图是程序运行后输出的图片,第一张图是原始音频时域波形图,第二张图是含有隐藏信息的音频时域波形图。

在这里插入图片描述
从上面的对比图中难以看出差异,我们将其放大,将横轴的显示范围更改为0-0.6秒。这样便能够明显地看出差异。
在这里插入图片描述

3. 提取隐藏信息代码实现(随机序列)

fid = fopen('music_new_secret.wav', 'r');
oa = fread(fid, inf, 'uint8');

m = oa;
n = length(oa) - 44;
for i = 1 : n
    w(i) = bitget(m(44 + i), 1);
end
fclose(fid);

rate = length(find(w ~= d)) / length(d);
  • 提取隐藏信息的实现部分是在程序的第4至第8行。第4行代码将含有隐藏信息的音频采样数据赋值给m。第5行代码定义了待提取的秘密数据的长度(这个长度要和秘密数据d的长度保持一致,如果不一致,最终将会得到有缺失的秘密数据或者是多余的乱码,至少这个长度不能大于音频采样数据的长度-44)。第6行至第8行利用bitget函数,将m从第45个元素开始的每一位的最低位提取出来,存储到w中,最终,w就是秘密数据。
  • 第11行代码计算了一下误码率,因为本程序在提取秘密数据前没有对含有隐藏信息的音频做任何处理,因此这里得到的误码率rate为0。

4. 二值图像作为秘密数据

从第2节和第3节中,应该已经知道了信息隐藏以及信息提取的原理了。
接下来,我们把一副二值图像当做秘密数据来进行隐藏。

4.1 图像信息隐藏的代码实现

首先给出待隐藏的图片,如下图所示。
在这里插入图片描述
下面为图像信息隐藏的代码。

clc;
clear;
fid = fopen('music_new.wav', 'rb');
oa = fread(fid, inf, 'uint8');
fclose(fid);

n = length(oa) - 44;
io = imread('school.bmp');
[row col] = size(io);
wi = io(:);
if row * col > n
    error('音频载体太小,请更换载体');
end
info_hd_audio = oa;
for k = 1 : row * col
    info_hd_audio(44 + k) = bitset(info_hd_audio(44 + k), 1, wi(k));
end

fid = fopen('music_new_secret.wav', 'wb');
fwrite(fid, info_hd_audio, 'uint8');
fclose(fid);

figure;
[y1, Fs] = audioread('music_new.wav');
x1 = (0:length(y1) - 1) / Fs;
subplot(2, 1, 1);
plot(x1, y1);
axis([0 max(x1) -1 1]);
xlabel('Time / (s)');ylabel('Amplitude');title('original audio');

[y2, Fs] = audioread('music_new_secret.wav');
x2 = (0:length(y2) - 1) / Fs;
subplot(2, 1, 2);
plot(x2, y2);
axis([0 max(x2) -1 1]);
xlabel('Time / (s)');ylabel('Amplitude');title('information hiding audio');


figure;
subplot(2, 1, 1); plot(x1, y1); axis([0 0.6 -0.05 0.05]);
xlabel('Time / (s)');ylabel('Amplitude');title('original audio');

subplot(2, 1, 2); plot(x2, y2); axis([0 0.6 -0.05 0.05]);
xlabel('Time / (s)');ylabel('Amplitude');title('information hiding audio');

代码的第11行到第13行是用来判断音频载体的大小是否足够用来隐藏待隐藏的图片。原理是:将原始音频采样数据oa减去44(wav文件的格式说明)后赋值给n,n即为这个音频最多能隐藏的信息的大小(单位为bit),再将二值图像的总的像素个数(row * col)与n作比较,如果像素个数小于等于n,那么程序继续执行,否则,载体不足以隐藏这个二值图像。

除此之外,此代码的核心原理与隐藏信息为随机序列的代码(第2节)一致,因此不做过多介绍。

下图是程序运行后输出的图片,第一张图是原始音频时域波形图,第二张图是含有隐藏信息的音频时域波形图。

在这里插入图片描述
从上面的对比图中难以看出差异,我们将其放大,将横轴的显示范围更改为0-0.6秒。这样便能够明显地看出差异。
在这里插入图片描述

4.2 对含有图像的音频进行攻击(压缩)的代码实现

clc;
clear;
[y,Fs] = audioread('music_new_secret.wav');
x = (0:length(y) - 1) / Fs;
y1 = y * 0.8;

subplot(2, 1, 1);
plot(x, y);
axis([0 max(x) -1 1]);
xlabel('Time / (s)');ylabel('Amplitude');title('information hiding audio');

subplot(2, 1, 2);
plot(x, y1);
axis([0 max(x) -1 1]);
xlabel('Time / (s)');ylabel('Amplitude');title('attacked audio');

audiowrite('music_new_secret_attacked.wav', y1, Fs);

对嵌入图像的音频进行压缩攻击测试。代码的第5行即是对音频的幅值进行压缩,压缩的倍数为0.8。

下图是程序运行后输出的图片,第一张图是含有图像的音频时域波形图,第二张图是幅值压缩0.8倍后的含有图像的音频时域波形图。
在这里插入图片描述

4.3 提取隐藏图像的代码实现

clc;
clear;
orig_pic = imread('school.bmp');


fid = fopen('music_new_secret.wav', 'r');
oa1 = fread(fid, inf, 'uint8');
fclose(fid);
n1 = 40000;
for i = 1 : n1
    w1(i) = bitget(oa1(44 + i), 1);
end
w1 = w1';
m1 = reshape(w1, 200, 200);
figure;
subplot(1, 2, 1);imshow(orig_pic);title('original picture');
subplot(1, 2, 2);imshow(m1);title('not attacked extracted picture');
imwrite(m1, 'school_extract.bmp', 'bmp');


fid = fopen('music_new_secret_attacked.wav', 'r');
oa2 = fread(fid, inf, 'uint8');
fclose(fid)
n2 = 40000;
for i = 1 : n2
    w2(i) = bitget(oa2(44 + i), 1);
end
w2 = w2';
m2 = reshape(w2, 200, 200);
figure;
subplot(1, 2, 1);imshow(orig_pic);title('original picture');
subplot(1, 2, 2);imshow(m2);title('attacked extracted picture');
imwrite(m2, 'school_extract_attacked.bmp', 'bmp');


代码运行后输出两张图片,第一张图片是原图片由未被攻击的含有图像的音频中提取到的图片的对比图,如下图所示。
在这里插入图片描述
第二张图片是原图片由被攻击的含有图像的音频中提取到的图片的对比图,如下图所示。
在这里插入图片描述
由此可见,LSB算法的鲁棒性很差。

4.4 更改载体音频重做一次实验

上面做过的所有实验,采用的载体音频都是同一段音频,即一段长达29秒的歌曲前奏。

接下来,我将载体音频改为本人录制的一段录音。录音的环境为空旷环境,内容为口播“一、二、三”。

用到的所有代码与上面的代码都是一样的,仅仅是读取的音频文件不同。因此直接给出结果图。

下图是图像信息隐藏的代码运行后输出的图片,第一张图是原始音频时域波形图,第二张图是含有隐藏信息的音频时域波形图。
在这里插入图片描述
从上面的对比图中难以看出差异,我们将其放大,将横轴的显示范围更改为0-0.6秒。这样便能够明显地看出差异。
在这里插入图片描述
下图是对含有图像的音频进行攻击(压缩)的代码运行后输出的图片,第一张图是含有图像的音频时域波形图,第二张图是幅值压缩0.8倍后的含有图像的音频时域波形图。
在这里插入图片描述
最后,提取隐藏图像的代码运行后输出两张图片,第一张图片是原图片由未被攻击的含有图像的音频中提取到的图片的对比图,如下图所示。
在这里插入图片描述
第二张图片是原图片由被攻击的含有图像的音频中提取到的图片的对比图,如下图所示。
在这里插入图片描述
由此可见,LSB算法的鲁棒性很差。

5. LSB算法的特点

LSB算法的特点是:

  • 本身简单易实现,音频信号里可编码的数据量大 。
  • 采用流加密方式分别对数据本身和嵌入过程进行加密,其安全性完全依赖于密钥,如果选择伪随机性能好的密钥产生机制,则可以做到“一次一密”。
  • 信息嵌入和提取算法简单,速度快。
  • 对信道干扰及数据操作的抵抗力很差,事实上,信道干扰、数据压缩、滤波、重采样、时域缩放等都会破坏编码信息。

6. 其他音频信息隐藏算法

  • 回声隐藏算法
  • 相位隐藏算法
  • 傅氏变换域算法
  • 离散余弦变换域算法
  • 小波变换域算法

猜你喜欢

转载自blog.csdn.net/mahoon411/article/details/111009739