BMP图片信息隐藏

2024-03-19 05:20
文章标签 图片 隐藏 信息 bmp

本文主要是介绍BMP图片信息隐藏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

信息隐藏技术利用了人类感觉器官对数字信号的感觉冗余,将待隐信息(类似噪声)隐藏在载体文件(如图像、视频、声音)中,使得人的感官(眼、耳)无法觉察到载体文件外部表现上的变化,从而实现隐蔽通信。将文件隐藏于BMP文件中是最简单的隐藏信息的方式。

LSB(Least Significant Bit Embedding)算法即最低有效位嵌入算法。改变每个RGB字节的最低有效位,将其作为容器,将需要隐藏的信息按位分离,放入最低有效位中。插入了信息后的图片仍是一副完整的图片,与原图片在肉眼中区分不出来,达到隐藏信息的效果。本文编程实现了LSB算法,隐藏一个RAR文件至一个BMP文件中,并实现了对应的提取方法。

1. 设计思路

首先,我们需要了解BMP文件的组成结构。BMP文件由四部分组成:位图文件头、位图信息头、调色板数据和实际位图数据。其中前三部分占据了BMP文件的前54个字节,也就是说LSB算法是保持原BMP文件的前54位不动,而对BMP文件的“实际位图数据”部分进行改动。

然后,我们开始想办法用C语言来实现LSB算法,主要分为判断图片是否能隐藏文件、LSB嵌入和LSB提取三个部分。

1.1 判断图片是否能隐藏文件

在向原始BMP图片中隐藏文件之前,我设计了一个函数来判断原始bmp图片是否能容纳待隐藏文件,若能,返回1;否则,返回0。这个函数的代码如下:

//判断原始bmp图片是否能容纳待隐藏文件,若能,返回1;否则,返回0 
int containOK(FILE *pic, FILE *file, long *picLen, long *fileLen) {//取bmp图片文件长度 fseek(pic, 0, SEEK_END);  //将文件指针置尾 *picLen = ftell(pic);	  //取文件指针当前位置 rewind(pic);              //将文件指针重指向文件头 //取待隐藏文件长度 fseek(file, 0, SEEK_END);  //将文件指针置尾 *fileLen = ftell(file);   //取文件指针当前位置rewind(file);             //将文件指针重指向文件头 if((*fileLen) * 8 > *picLen) return 0;else                  //当位图文件大于待隐藏文件的8倍时,可以容纳return 1;
}

1.2 LSB嵌入

然后,我开始设计LSB嵌入:首先把要隐藏的文件的信息进行按位分离,再把原始位图文件的“实际位图数据”部分的每一个字节的末位都进行清零操作,然后将已经按位分离的待隐藏文件数据逐个附加到原始位图文件“实际位图数据”部分的每一个字节的末位。具体的函数实现如下:

//LSB嵌入 
void encrypt(char *inPic, char *outPic, char *file) {FILE *in;      //指向原始位图文件的指针 FILE *out;     //指向新位图文件的指针 FILE *fil;     //指向待隐藏文件的指针 long picLen;   //原始位图文件的长度 long fileLen;  //待隐藏文件的长度 if ((in = fopen(inPic,"rb")) == NULL) {printf("Cannot open the original bitmap file!\n");exit(0);}if ((out = fopen(outPic,"wb")) == NULL) {printf("Cannot open the output bitmap file!\n");exit(0);}if ((fil = fopen(file,"rb")) == NULL) {printf("Cannot open the file to be hidden!\n");exit(0);}if (!containOK(in, fil, &picLen, &fileLen)) {printf("The file is too large!\n");exit(0);}//储存待隐藏文件信息 int i, j;char ch;char *temp = (char *)malloc(8 * fileLen);i = 0;while (!feof(fil)) {  //将待隐藏文件按位存放于temp数组中 ch = fgetc(fil);for(j = 0; j < 8; j++) temp[i++] = 0x01 & (ch >> j);}j = 0;for(i = 1; !feof(in); i++) {if (i <= 54) fputc(fgetc(in), out);  //原位图文件前54个字节保持不变else {if (j < fileLen * 8)   //将待隐藏文件数据逐个附加到原位图文件每个字节末位 fputc((fgetc(in) & 0xfe) + temp[j++], out);else fputc(fgetc(in) & 0xfe, out);}} //关闭文件 fclose(in);  fclose(out);fclose(fil); 
} 

1.3 LSB提取

LSB提取,就是将位图文件第54个字节之后的每个字节末位信息提取出来,每8个组成一个字符,再输出到文件中,具体实现如下:

//LSB提取
void decrypt(char *inPic, char *outFile) {FILE *in;   //指向位图文件的指针 FILE *out;  //指向提取出的文件的指针 if((in = fopen(inPic,"rb")) == NULL) {printf("Cannot open the bitmap file!\n");exit(0); } if((out = fopen(outFile,"wb")) == NULL) {printf("Cannot open the output file!\n");exit(0); } fseek(in, 54L, 0);  //将文件指针指向距文件头54字节处 char ch;do {ch = 0;int j;for( j = 0; j < 8; j++) {ch += (fgetc(in) & 0x01) << j; //把每8个字节的末位信息组成一个字符 }fputc(ch, out);    //输出 } while (!feof(in));//关闭文件 fclose(in);fclose(out); 
}

至此,LSB算法实现已经大致完成。

2. 运行结果

在运行程序lsb.c前,我准备了一个原始位图文件1.bmp和一个待隐藏文件funny.rar,并将它们与程序lsb.c放在同一目录下:
输入文件准备
然后,我开始运行我的程序,将funny.rar隐藏到1.bmp中,生成的新位图文件保存为2.bmp。接着对2.bmp进行LSB提取,提取出的文件保存为3.bmp:
运行结果
打开程序所在目录,可以看到多出了两个文件2.bmp和3.rar:
运行后的目录
原始位图文件1.bmp和加密后的位图文件2.bmp对比如下,可以发现肉眼很难发现差异。
两张图片肉眼的差异
隐藏前的funny.rar与提取出的3.rar解压缩对比如下,两个文件的修改日期和大小均一致,查看内容也一致,因此提取成功。
隐藏文件与还原文件

3. 源代码

以上就是C语言实现LSB算法的过程啦,完整源代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>//判断原始bmp图片是否能容纳待隐藏文件,若能,返回1;否则,返回0 
int containOK(FILE *pic, FILE *file, long *picLen, long *fileLen) {//取bmp图片文件长度 fseek(pic, 0, SEEK_END);  //将文件指针置尾 *picLen = ftell(pic);	  //取文件指针当前位置 rewind(pic);              //将文件指针重指向文件头 //取待隐藏文件长度 fseek(file, 0, SEEK_END);  //将文件指针置尾 *fileLen = ftell(file);    //取文件指针当前位置rewind(file);              //将文件指针重指向文件头 if((*fileLen) * 8 > *picLen) return 0;else                       //当位图文件大于待隐藏文件的8倍时,可以容纳  return 1;          
}//LSB嵌入 
void encrypt(char *inPic, char *outPic, char *file) {FILE *in;      //指向原始位图文件的指针 FILE *out;     //指向新位图文件的指针 FILE *fil;     //指向待隐藏文件的指针 long picLen;   //原始位图文件的长度 long fileLen;  //待隐藏文件的长度 if ((in = fopen(inPic,"rb")) == NULL) {printf("Cannot open the original bitmap file!\n");exit(0);}if ((out = fopen(outPic,"wb")) == NULL) {printf("Cannot open the output bitmap file!\n");exit(0);}if ((fil = fopen(file,"rb")) == NULL) {printf("Cannot open the file to be hidden!\n");exit(0);}if (!containOK(in, fil, &picLen, &fileLen)) {printf("The file is too large!\n");exit(0);}//储存待隐藏文件信息 int i, j;char ch;char *temp = (char *)malloc(8 * fileLen);i = 0;while (!feof(fil)) {  //将待隐藏文件按位存放于temp数组中 ch = fgetc(fil);for(j = 0; j < 8; j++) temp[i++] = 0x01 & (ch >> j);}j = 0;for(i = 1; !feof(in); i++) {if (i <= 54) fputc(fgetc(in), out);  //原位图文件前54个字节保持不变else {if (j < fileLen * 8)   //将待隐藏文件数据逐个附加到原位图文件每个字节末位 fputc((fgetc(in) & 0xfe) + temp[j++], out);else fputc(fgetc(in) & 0xfe, out);}} //关闭文件 fclose(in);  fclose(out);fclose(fil); 
} //LSB提取
void decrypt(char *inPic, char *outFile) {FILE *in;   //指向位图文件的指针 FILE *out;  //指向提取出的文件的指针 if((in = fopen(inPic,"rb")) == NULL) {printf("Cannot open the bitmap file!\n");exit(0); } if((out = fopen(outFile,"wb")) == NULL) {printf("Cannot open the output file!\n");exit(0); } fseek(in, 54L, 0);  //将文件指针指向距文件头54字节处 char ch;do {ch = 0;int j;for( j = 0; j < 8; j++) {ch += (fgetc(in) & 0x01) << j; //把每8个字节的末位信息组成一个字符 }fputc(ch, out);    //输出 } while (!feof(in));//关闭文件 fclose(in);fclose(out); 
}int main() {char inPic[100]; //储存原始位图文件名 char outPic[100];//储存生成位图文件名 char file[100];  //储存加密文件名 printf("**********LSB嵌入**********\n");printf("请输入原始位图文件名:\n");scanf("%s",inPic);printf("请输入生成位图文件名:\n");scanf("%s",outPic);printf("请输入加密文件名:\n");scanf("%s",file);encrypt(inPic, outPic, file);printf("LSB嵌入完成!\n"); char infile[100];  //储存待解密位图名 char outfile[100]; //储存提取出的文件名 printf("**********LSB提取**********\n");printf("请输入待解密位图名:\n");scanf("%s", infile); printf("请输入提取出保存的文件名:\n"); scanf("%s", outfile);decrypt(infile, outfile);printf("LSB提取完成!\n");return 0;
}

这篇关于BMP图片信息隐藏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/824922

相关文章

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

Spring MVC 图片上传

引入需要的包 <dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.1</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-

Prompt - 将图片的表格转换成Markdown

Prompt - 将图片的表格转换成Markdown 0. 引言1. 提示词2. 原始版本 0. 引言 最近尝试将图片中的表格转换成Markdown格式,需要不断条件和优化提示词。记录一下调整好的提示词,以后在继续优化迭代。 1. 提示词 英文版本: You are an AI assistant tasked with extracting the content of

研究人员在RSA大会上演示利用恶意JPEG图片入侵企业内网

安全研究人员Marcus Murray在正在旧金山举行的RSA大会上公布了一种利用恶意JPEG图片入侵企业网络内部Windows服务器的新方法。  攻击流程及漏洞分析 最近,安全专家兼渗透测试员Marcus Murray发现了一种利用恶意JPEG图片来攻击Windows服务器的新方法,利用该方法还可以在目标网络中进行特权提升。几天前,在旧金山举行的RSA大会上,该Marcus现场展示了攻击流程,

恶意PNG:隐藏在图片中的“恶魔”

&lt;img src=&quot;https://i-blog.csdnimg.cn/blog_migrate/bffb187dc3546c6c5c6b8aa18b34b962.jpeg&quot; title=&quot;214201hhuuhubsuyuukbfy_meitu_1_meitu_2.jpg&quot;/&gt;&lt;/strong&gt;&lt;/span&gt;&lt;

PHP抓取网站图片脚本

方法一: <?phpheader("Content-type:image/jpeg"); class download_image{function read_url($str) { $file=fopen($str,"r");$result = ''; while(!feof($file)) { $result.=fgets($file,9999); } fclose($file); re

Linux命令(11):系统信息查看命令

系统 # uname -a # 查看内核/操作系统/CPU信息# head -n 1 /etc/issue # 查看操作系统版本# cat /proc/cpuinfo # 查看CPU信息# hostname # 查看计算机名# lspci -tv # 列出所有PCI设备# lsusb -tv