使用F5方法在MP3音频上进行简单隐写

2022/10/09 Steganography 共 1828 字,约 6 分钟

矩阵编码隐写方案设计

设计一个矩阵编码方案(参数不能与讲义中相同),并给出它的一次嵌入与提取计算实例,同时计算嵌入效率

基本设定

  • 基于F5方法,使用 (1,15,4) 矩阵编码嵌入秘密消息

实验设置

  • 实验环境为 MacOS-v12.6
  • mp3编码使用 lame 3.100,解码使用 lame 中包含的第三方库 mpglib
  • 测试音频为 3 条长度 10s,采样率为 44.1 kHz,双声道的 wav 音频。

隐写实现过程

实验优化:

  1. 为了实现上的简单,不进行 QMDCT 系数置乱
  2. 仅在同一region内进行嵌入,每次嵌入从region的第1个QMDCT系数开始
  3. 数值修改上采用 阈值内符号位翻转。本次实验中阈值设置为1,即只对正负1进行嵌入,需要修改时进行符号位翻转

实验流程:

  1. 在 lame 编码过程中提取 QMDCT 系数,在QMDCT 系数上嵌入1000个随机比特
  2. 对生成的 mp3 音频再进行解码,从其 QMDCT 系数提取消息
  3. 对比嵌入和提出的消息,验证正确性

实验结果及效率计算

误码率:

  • 1.wav: $0.00$
  • 2.wav: $0.00$
  • 3.wav: $0.00$

理论嵌入效率:

\[e = \cfrac {平均每载体样本点承载的信息比特}{平均每载体样点被修改量}bit/次修改 = \cfrac 1{ \frac14 \times \frac{15}{16}} = 4.27\]

实际嵌入效率:

  • 1.wav: $\frac{1000}{241}=4.15$
  • 2.wav: $\frac{1000}{235}=4.26$
  • 3.wav: $\frac{1000}{230}=4.35$

修改核心代码

    static char s[2000] = {};
    static int fix_tot = 0;
    static int idx = 0;
    static int tot = 0;
    static int flag = 0;
    int pos[16];

    if(!flag){
        flag = 1;
        FILE *msg_input = fopen("msg.txt", "r");
        fscanf(msg_input,"%s",s);
        tot = strlen(s);
        for(int i=0;s[i];i++)
            s[i]-='0';
        fclose(msg_input);
    }
    FILE *qmdct_out = fopen("qmdct_encode.txt", "a+");


    for (gr = 0; gr < cfg->mode_gr; gr++)
        for (ch = 0; ch < cfg->channels_out; ch++){
            int have = 1, sum =0;
            for(int i =0; i < 576; i++){
                if(idx < tot){
                    int v = gfc->l3_side.tt[gr][ch].l3_enc[i];
                    if(v == 1){
                        pos[have] = i;
                        if(gfc->l3_side.tt[gr][ch].xr[i] < 0)
                            sum ^= have;
                        have++;
                    }

                    if(have == 16){
                        int msg_v= s[idx] * 8 + s[idx+1] * 4 + s[idx+2] * 2 + s[idx+3]; 
                        sum ^= msg_v;
                        if(sum) {fix_tot++; gfc->l3_side.tt[gr][ch].xr[pos[sum]] *= -1;}
                        idx += 4;
                        sum = 0;
                        have = 1;
                    }
                }   
            }
        }

提取核心代码

  FILE *msg_out = fopen("msg_out.txt", "a+");
    static int ext_tot = 0;
    int tot = 1000;
    int have = 0;
    int sum = 0;
    for(int i = 0; i < 576; i++){
        if(ext_tot<tot && (qmdct[i]==1 || qmdct[i]==-1)){
            have++;
            if(qmdct[i] == -1)
                sum ^= have;
            if(have == 15){
                ext_tot += 4;
                for(int j = 3; j >= 0; j--){
                    fprintf(msg_out,"%d",(sum>>j)&1);
                }
                have = 0; 
                sum = 0;
            }
        }
    }

复现方法

  1. 已将源代码编译成可执行文件lame(MaxOS系统下)
  2. 将lame、wav音频文件和消息文件(需要命名为msg.txt)放在同一文件夹下
  3. 在该文件路径执行:
    • ./lame input.wav middle.mp3
    • ./lame –decode middle.mp3 final.wav
    • 第一条命令为嵌入,第二条命令为提取
  4. 会生成out_msg.txt文件

文档信息

Search

    Table of Contents