JSteg信息隐藏算法

目录

  • 实验环境
  • 系统设计
    • JSteg信息隐藏算法
      • JSteg信息隐藏算法替换规则
      • 嵌入算法
      • 提取算法
      • JSteg信息隐藏算法缺陷分析
  • 系统实现
    • 嵌入算法
      • JSTEG_simulation.m
      • stego.m
    • 提取算法
      • JSTEG_extract.m
      • extract.m
  • 实验结果
    • 信息嵌入
    • 信息提取
    • 信息比对
  • 参考文献

实验环境

  • MATLAB
  • 从JPEG图片中提取DCT系数的程序jpeg_toolbox,下载地址为http://dde.binghamton.edu/download/jpeg_toolbox.zip。

程序来源:Simulator of nsF5 embedding (Matlab):http://dde.binghamton.edu/download/nsf5simulator/。

.mex文件是由C或Fortran语言编写的代码经过matlab编译器处理而生成的二进制文件。它是可以被matlab解释器自动装载并执行的动态链接程序。

mex封装包名称与操作系统的对应关系如下:
mexa64 : 64-bit Linux
mexglx : 32-bit Linux
mexw32 : 32-bit Windows
mexw64 : 64-bit Windows

系统设计

JSteg信息隐藏算法

       JSteg信息隐藏算法是LSB替换思想在DCT域的实现
       JSteg信息隐藏算法嵌入过程的关键步骤就是将原始图像的AC系数中最低的一个位平面“替换”为要隐藏的秘密信息。这里的“替换”遵循如下规则:
       (1)跳过-1、0、1;
       (2)若AC系数为2i,秘密比特为0,该系数不变;
       (3)若AC系数为2i,秘密比特为1,该系数变为2i+1;
       (4)若AC系数为2i+1,秘密比特为0,该系数变为2i;
       (5)若AC系数为2i+1,秘密比特为1,该系数不变。

JSteg信息隐藏算法替换规则

JSteg信息隐藏算法_第1张图片
       由此规则可知:载密图像的AC系数中,-1、0、1不包含任何秘密信息。此外,其他的AC系数中的最低比特位即为秘密比特。只需将除-1、0、1外的其他AC系数的最低比特位取出,即可恢复秘密信息。

嵌入算法

       Steg信息隐藏算法嵌入流程如下:
       (1)提取原始图像的DCT系数,获取AC系数;
       (2)将秘密信息转换为二进制序列,并按照JSteg信息隐藏算法替换规则,将原始图像中AC系数的最低比特位替换为二进制序列中的每一比特信息;
       (3)在替换过程结束后,将原始图像中AC系数的二进制数据转换回十进制数据,保存为载密图像。

提取算法

       与嵌入算法对应,Steg信息隐藏算法提取流程如下:
       (1)提取载密图像的DCT系数,获取AC系数;
       (2)将除-1、0、1外的其他AC系数的最低比特位取出,根据嵌入顺序进行组合得到原秘密序列。

JSteg信息隐藏算法缺陷分析

       根据JSteg信息隐藏算法替换规则,载密图像的DCT直方图会出现“成对现象”

系统实现

嵌入算法

JSTEG_simulation.m

function [nzAC] = JSTEG_simulation(COVER, STEGO, message)

try
    jobj = jpeg_read(COVER); %读取cover图片
    PrimeDCT = jobj.coef_arrays{1}; %读取DCT系数
    DCT = PrimeDCT;
catch
    error('ERROR (problem with the cover image)');
end

nzAC = numel(DCT) - numel(DCT(1:8:end, 1:8:end)); %计算AC系数个数

messageLen = length(message);

changeable = true(size(DCT)); %生成一个布尔矩阵
changeable(1:8:end, 1:8:end) = false; %DC系数的位置置为false
posAC = find(changeable); %找出布尔矩阵中为true的位置,即AC系数的位置

idD = 1;
idMsg = 1;

while idMsg <= messageLen
    while idD <= nzAC && abs(DCT(posAC(idD))) <= 1
        idD = idD + 1;
    end

    %信息过长
    if idD > nzAC
        error('ERROR (too long message)')
    end

    DCTInfo = DCT(posAC(idD));
    if message(idMsg) ~= mod(DCTInfo, 2) %LSB与隐藏信息不同
        if DCTInfo < 0
            if mod(DCTInfo, 2)
                DCT(posAC(idD)) = DCTInfo + 1;
            else
                DCT(posAC(idD)) = DCTInfo - 1;
            end
        else
            if mod(DCTInfo, 2)
                DCT(posAC(idD)) = DCTInfo - 1;
            else
                DCT(posAC(idD)) = DCTInfo + 1;
            end
        end
    end
    idD = idD + 1;
    idMsg = idMsg + 1;
end

histogram(DCT)

%%% save the resulting stego image
try
    jobj.coef_arrays{1} = DCT;
    jobj.optimize_coding = 1;
    jpeg_write(jobj, STEGO);
catch
    error('ERROR (problem with saving the stego image)');
end

%显示未嵌入信息的图像
subplot(3, 2, 1);
imshow(COVER);
title('未嵌入信息的图像');

%显示未嵌入信息的图像的DCT系数直方图
subplot(3, 2, [3, 4]);
histogram(PrimeDCT);
axis([-10, 10, 0, 2 * 1e4]);
title('嵌入前的图像DCT系数直方图');

%显示嵌入信息的图像
subplot(3, 2, 2);
imshow(STEGO);
title('嵌入信息的图像');

%显示嵌入信息的图像的DCT系数直方图
subplot(3, 2, [5, 6]);
histogram(DCT);
axis([-10, 10, 0, 2 * 1e4]);
title('嵌入后的图像DCT系数直方图');

stego.m

COVER = 'cover.jpg';
STEGO = 'stego.jpg';

message = randi([0, 1], 1, 25000); %生成随机数,作为隐藏信息
save('message', 'message', '-ascii'); %保存秘密信息

tic;
[nzAC] = JSTEG_simulation(COVER, STEGO, message);
T = toc;

fprintf('-----------------------------------\n');
fprintf('JSTEG simulation finished\n');
fprintf('cover image: %s\n', COVER);
fprintf('stego image: %s\n', STEGO);
fprintf('number of nzACs in cover: %i\n', nzAC);
fprintf('elapsed time: %.4f seconds\n', T);
fprintf('-----------------------------------\n');

提取算法

JSTEG_extract.m

function message = JSTEG_extract(STEGO, messageLen)

try
    jobj = jpeg_read(STEGO); %读取stego图片
    DCT = jobj.coef_arrays{1}; %读取DCT系数
catch
    error('ERROR (problem with the stego image)');
end

changeable = true(size(DCT)); %生成一个布尔矩阵
changeable(1:8:end, 1:8:end) = false; %DC系数的位置置为false
changeable = find(changeable); %找出布尔矩阵中为true的位置,即AC系数的位置

idMsg = 1;
idD = 1;

nzAC = numel(DCT) - numel(DCT(1:8:end, 1:8:end)); %计算AC系数个数
message = linspace(0, 0, messageLen);

while idMsg <= messageLen
    while idD <= nzAC && abs(DCT(changeable(idD))) <= 1
        idD = idD + 1;
    end

    if idD > nzAC
        error('ERROR (wrong hiden message length)');
    end

    message(idMsg) = mod(DCT(changeable(idD)), 2);

    idMsg = idMsg + 1;
    idD = idD + 1;
end

extract.m

STEGO = 'stego.jpg';

messageLen = 25000;

tic;
messageHiden = JSTEG_extract(STEGO, messageLen);
T = toc;

save('messageHiden', 'messageHiden', '-ascii');
% 保存提取出来的秘密信息

fprintf('-----------------------------------\n');
fprintf('JSTEG extract finished\n');
fprintf('elapsed time: %.4f seconds\n', T);
fprintf('-----------------------------------\n');

实验结果

信息嵌入

       运行JSteg信息隐藏算法隐藏过程的实现代码stego.m。观察到嵌入完成,并且原始图像和载密相差甚微,DCT直方图出现“成对现象”。
JSteg信息隐藏算法_第2张图片

信息提取

       运行JSteg信息隐藏算法提取过程的实现代码extract.m。观察到提取完成。
JSteg信息隐藏算法_第3张图片

信息比对

       查看提取出来的秘密信息文件messageHiden,与原始秘密信息文件message比对,观察到提取出来的秘密信息是正确的。
信息比对

参考文献

       [1] 孔祥维等.多媒体信息安全实践教程.科学出版社

你可能感兴趣的:(图像信息隐藏,图像信息隐藏,jsteg,LSB,matlab,信息隐藏)