BMP图片信息隐藏实验

实验目标

        在BMP图片中实现ASCII码信息隐藏,并且可恢复密文。为了提高加密等级,采用将密文按每个比特隐藏进载体每个数据字节的方式。

前置知识

1.BMP位图

        BMP位图是一种与设备无关的图像文件格式,使用广泛,采用位映射存储格式,可选图片深度,支持BI_RGB(无压缩)、BI_RLE8和BI_RLE4等压缩方式。采取小端存储方式。

        BMP文件的数据按照文件头开始的先后分为4个部分:

        BMP文件头:说明文件的类型、大小、数据偏移量。

        位图信息头:说明图像的尺寸、深度、压缩方法、颜色索引数等特性。

        颜色表/调色板(可选):对于使用索引颜色的图像,颜色表包含图像中使用的所有颜色,这在颜色深度较低时非常常见。

        位图数据:根据biBitCountbiCompression的值,以不同的方式存储像素数据。

        BMP图像深度可选1bit、4bit、8bit、16bit、24bit及32bit。1bit深度下每个像素只能表示两种颜色,一般是黑和白;4~24bit深度下每个像素能从eq?2%5E%7B_%7Bn%7D%7D(n=4,8,16)种颜色中选取一种来表示;24位颜色模式允许每个像素直接定义其RGB值一般不使用颜色表;32bit深度在24bit深度基础上增加8bit表示像素透明度(alpha层)。

        根据BMP文件的结构,其文件头第11~14个字节保存了从文件头开始到实际图片数据之间的字节的偏移量,我们可以据此定位。

2.char类型

        在C语言标准中,char 类型的大小被定义为1个字节,并在绝大多数现代环境中占据8位bit。在此次实验中使用char型处理数据。

3.ASCII码

        ASCII码使用7或8位二进制数组合来表示128或256种字符。标准ASCII码使用7位二进制数(剩下一位固定为0)来表示所有的大写和小写字母,数字0到9、标点符号,以及在美式英语中使用的特殊控制字符。正好能保存在一个char型结构里。

逻辑分析

        要将密文逐比特隐藏进载体图片,首先要定位到位图数据起始处或数据内的其他什么地方,咱定位到起始处,然后要将密文比特与载体字节结合,再塞到载体中,并且密文结束后要给出一段有一定特征的比特,来标识密文的结束,信息隐藏就结束哩。然后为了读取密文,程序要定位到密文开始的地方,然后读到结束标志后停止,并翻译出信息就大功告成哩。

代码实现(C语言)

        首先我们的密文(ASCII码)要翻译成二进制数串。

// 将字符串转换为二进制

void string_to_binary(char *s, char *out)

{

    char *out_p = out;

    char *s_p = s;

    while (*s_p)

    {

        unsigned char c = *s_p++;

        for (int i = 7; i >= 0; --i)

        {

            *out_p = ((c & (1 << i)) ? '1' : '0');

            out_p++;

        }

    }

    *out_p = '\0';

}

         在原文件中获取图片偏移量(块中fp是指向BMP图片文件起始位置的指针)。

    // 获取图片偏移量

    fseek(fp, 10, SEEK_SET);

    unsigned char buffer[4];

    fread(buffer, 1, 4, fp);

    unsigned int picoffset = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);

        逐字节隐藏信息(c2change是操作数据用的一个char型变量,咱这里从原文件读数据,写入密文,再写入新文件;写入结束标志的话可以挑一个不会被使用的8位二进制作为结束标志在最后写入)。

    while (binary[i] != '\0')

    {

        fread(&c2change, 1, 1, fp);

        c2change = (c2change & 0xFE) | (binary[i] - '0');

        // fseek(fp_new, -1, SEEK_CUR);

        fwrite(&c2change, 1, 1, fp_new);

        i++;

    }

         提取信息时,定位到密文初始处,从每个字节中取出密文,凑齐8个就翻译出一个字符。(我这里以'0000 0000'作为结束标志)。

    while (1)

    {

        fread(&cthechange, 1, 1, fp);

        now_character = (now_character << 1) | (cthechange & 1);

        i++;

        if (i % 8 == 0)

        {

            // 判断是否为结束标志

            if (now_character == '\0')

            {

                out[j] = '\0';

                break;

            }

            else

            {

                out[j] = now_character;

                j++;

                i = 0;

            }

        }

    }

        然后再加点创建新文件、一些文件操作、一些变量定义啥的就完成辣!

代码测试

        好的,现在我们搞一个BMP位图:

4533b7b9715c46bab56fa7ccd791b9d8.bmp

        分辨率 64x54,位深度32

        隐藏密文1919810

        用winhex观察 

fbc420a49ad040828656824473e75de1.png 

        成功改写哩,让我们来对比下隐藏前后的两图:

41369a86ff2745308c8713b2b16a0576.png

        现在图中右侧即是隐藏了数据的图片,用魔棒工具选区后发现有一小部分像素未被选中,即是被改写哩,从图中左下,我选择了从下从左第一个像素点,可见其颜色'e4d2aa'变成了'e5d2aa'。另外从调色板可以看出,多了一些相相相相相相相相当相似的颜色,根本看不出来嘛!!!!

9746ca2943514323bc8b0267d40f6854.png

        从winhex上来看也是一片虚无口牙!!!!真是完美的隐藏!!!

518c5f6b43db43fd8205b90505af58ea.png

        咱的人机交互和操作也是丝滑得一匹吖!

一些问题

        我没写防止密文串二进制位数比BMP文件数据字节还多得检测,一次隐藏太多就完蛋了(悲)。

附上资源链接

        链接指向一压缩包,MD5值为 bad072fe7aa2de2245a4bab8a0001faf 。包中有一原BMP csdn.bmp和隐藏入1919810的csdn_new.bmp。还有我写的C语言代码,可以编译下玩玩。解压码是“csdn”。

        链接:https://pan.baidu.com/s/1pr6vKYYI7WqKRB--RUIgkQ?pwd=chvi 
        提取码:chvi 

 

  • 27
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值