信息隐藏(C语言实现BMP位图信息隐藏)

一、基础功能

(1)将指定的文本信息隐藏到24位bmp位图中。信息隐藏的具体实现方法为最低有效位(LSB)方法,将密文插入像素颜色值的最低有效位中,由此引发的RGB颜色值的微小变化人眼无法感知。

(2)从携密图像文件中恢复隐秘的文本信息。分析按照(1)中方法生成的携密图像,从中提取出密文的信息并输出,注意要将二进制密文还原成字符串。

二、升级功能

(1)先对待隐藏的文本信息加密,然后再将密文隐藏到24位bmp位图中。这里使用凯撒密码(密钥为3的移位密码)先将明文转换成密文后再隐藏到位图中。这样即使位图密码被截获,也不会泄露密文信息。

(2)从按照(1)中方法加密的位图中恢复隐秘的文本信息。这里先从位图文件中得到密文,然后用密钥恢复出明文信息。

三、C语言代码实现


#define _CRT_SECURE_NO_WARNINGS
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>

/*菜单*/

void myMenu() {
	printf(" * * * * * * * * * 菜     单 * * * * * * * * * * * * * * * * * *\n");
	printf("     1 直接将密文隐藏入图片中            2 直接解密图片中的密文              \n");
	printf("     3 通过移位密码加密后隐藏            4 通过移位密码解密密文              \n");
	printf("     5 退出系统                                     \n");
	printf(" * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n");
}

/*位图文件头*/
typedef uint16_t WORD;
typedef uint32_t DWORD;
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER {
	WORD bfType;//文件类型2
	DWORD bfSize;//文件大小4
	WORD bfReserved1;//保留字2
	WORD bfReserved2;//保留字2
	DWORD bfOffBits;//偏移量4
} BITMAPFILEHEADER;
#pragma pack()
/*位图信息头*/
typedef uint32_t LONG;
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER {
	DWORD biSize;//长度
	LONG biWidth;//宽度
	LONG biHeight;//高度
	WORD biPlanes;//1
	WORD biBitCount;//颜色位数
	DWORD biCompression;//位图是否压缩
	DWORD biSizeImage;//位图大小
	LONG biXPelsPerMeter;//水平分辨率
	LONG biYPelsPerMeter;//垂直分辨率
	DWORD biClrUsed;//颜色数量
	DWORD biClrImportant;//重要颜色数
} BITMAPINFOHEADER;
#pragma pack()


/*显示文件头*/
void show_bit_map_file_header(BITMAPFILEHEADER* p)
{
	printf("bfType=%04x\n", p->bfType);
	printf("bfSize=%d\n", p->bfSize);
	printf("bfReserved1=%d\n", p->bfReserved1);
	printf("bfReserved2=%d\n", p->bfReserved2);
	printf("bfOffBits=%d\n", p->bfOffBits);
}
/*显示信息头*/
void show_bit_map_info_header(BITMAPINFOHEADER* p)
{
	printf("biSize=%d\n", p->biSize);
	printf("biWidth=%d\n", p->biWidth);
	printf("biHeight=%d\n", p->biHeight);
	printf("biPlanes=%d\n", p->biPlanes);
	printf("biBitCount=%d\n", p->biBitCount);
	printf("biCompression=%d\n", p->biCompression);
	printf("biSizeImage=%d\n", p->biSizeImage);
	printf("biXPelsPerMeter=%d\n", p->biXPelsPerMeter);
	printf("biYPelsPerMeter=%d\n", p->biYPelsPerMeter);
	printf("biClrUsed=%d\n", p->biClrUsed);
	printf("biClrImportant=%d\n", p->biClrImportant);
}

/*加密图片*/
void show_bmp(char* name1, char* name2)
{
	BITMAPFILEHEADER bit_map_file_header;
	BITMAPINFOHEADER bit_map_info_header;

	/*将文件头和信息头存储*/
	char ch = 0;
	FILE* pfr = fopen(name1, "rb");
	FILE* pfw = fopen(name2, "wb");
	/*错误处理*/
	if (NULL == pfw)
		perror("open file test2.txt");
	if (NULL == pfr)
		perror("open file test1.txt");
	/*将文件头和信息头存储*/
	fread(&bit_map_file_header, sizeof(bit_map_file_header), 1, pfr);
	fread(&bit_map_info_header, sizeof(bit_map_info_header), 1, pfr);
	/*将文件头和信息头写入*/
	fwrite(&bit_map_file_header, sizeof(bit_map_file_header), 1, pfw);
	fwrite(&bit_map_info_header, sizeof(bit_map_info_header), 1, pfw);

	/*提取RGB数据长度*/
	int IMAGE_SIZE = bit_map_file_header.bfSize;
	/*移动指针*/
	fseek(pfr, 54, SEEK_SET);
	fseek(pfw, 54, SEEK_SET);

	/*输入密文*/
	char password[100];
	int pin[800];
	printf("请输入要加密的信息:");
	scanf("%s", password);
	int p = 0;
	for (int k = 0; k < strlen(password); k++)
	{
		int asc = password[k];
		int y, a[8] = { 0,0,0,0,0,0,0,0 };
		/*转换为二进制*/
		for (int i = 7; asc != 0; i--)
		{
			y = asc % 2;
			asc = asc / 2;
			a[i] = y;
		}
		for (int j = 0; j < 8; j++)
		{
			pin[p] = a[j]; //printf("%d", pin[p]);
			p += 1; //printf("%d ", p);
		}
	}
	/*生成图片*/
	int g = 0, q = 0;
	while (!feof(pfr))
	{
		ch = fgetc(pfr);
		if (g < p + strlen(password))
		{
			if (g % 9 != 0)
			{
				if ((ch & 0x01) && pin[q] == 0)
				{
					ch = ch - 1;
				}
				if (!(ch & 0x01) && pin[q] == 1)
				{
					ch = ch + 1;
				}
				q++;
			}
			g++;
		}
		fputc(ch, pfw);
	}

	fclose(pfr);
	fclose(pfw);
}

/*解密图片*/
void get_bmp(char* name)
{
	char ch = 0;
	FILE* pfr = fopen(name, "rb");
	fseek(pfr, 54, SEEK_SET);
	int ans = 0;
	int q = 0;
	int v = 8;
	printf("密码为:");
	/*翻译密码*/
	while (1)
	{
		ch = fgetc(pfr);
		if (q % 9 != 0)
		{
			v -= 1;
			ans += (ch & 0x01) * pow(2, v);
		}
		q += 1;
		if (v == 0)
		{
			if ((ans >= 65 && ans <= 90) || (ans >= 97 && ans <= 122))
			{
				printf("%c", ans);
				v = 8;
				ans = 0;
			}
			else
				break;
		}
	}
	printf("\n");
}

/*移位密码——加密*/
void encryption1(char* name1, char* name2)
{
		char C[100];
		char M[100];
		int K = 3, i;
		//加密
		printf("请输入明文M(不可输入空白串):");
		scanf("%s", M);
		//gets(M);
		for (i = 0; M[i] != '\0'; i++)
		{
			if (M[i] >= 'a' && M[i] <= 'z')
			{
                C[i] = (M[i] - 'a' + K) % 26 + 'a';
			}
			else if (M[i] >= 'A' && M[i] <= 'Z')
			{
				C[i] = (M[i] - 'A' + K) % 26 + 'A';
			}
		}	
		C[i] = '\0';
		//printf("加密后的密文是:\n%s\n", C);
		BITMAPFILEHEADER bit_map_file_header;
		BITMAPINFOHEADER bit_map_info_header;

		/*将文件头和信息头存储*/
		char ch = 0;
		FILE* pfr = fopen(name1, "rb");
		FILE* pfw = fopen(name2, "wb");
		/*错误处理*/
		if (NULL == pfw)
			perror("open file test2.txt");
		if (NULL == pfr)
			perror("open file test1.txt");
		/*将文件头和信息头存储*/
		fread(&bit_map_file_header, sizeof(bit_map_file_header), 1, pfr);
		fread(&bit_map_info_header, sizeof(bit_map_info_header), 1, pfr);
		/*将文件头和信息头写入*/
		fwrite(&bit_map_file_header, sizeof(bit_map_file_header), 1, pfw);
		fwrite(&bit_map_info_header, sizeof(bit_map_info_header), 1, pfw);

		/*提取RGB数据长度*/
		int IMAGE_SIZE = bit_map_file_header.bfSize;
		/*移动指针*/
		fseek(pfr, 54, SEEK_SET);
		fseek(pfw, 54, SEEK_SET);

		/*输入密文*/
		int pin[800];
		int p = 0;
		for (int k = 0; k < strlen(C); k++)
		{
			int asc = C[k];
			int y, a[8] = { 0,0,0,0,0,0,0,0 };
			/*转换为二进制*/
			for (int i = 7; asc != 0; i--)
			{
				y = asc % 2;
				asc = asc / 2;
				a[i] = y;
			}
			for (int j = 0; j < 8; j++)
			{
				pin[p] = a[j]; //printf("%d", pin[p]);
				p += 1; //printf("%d ", p);
			}
		}
		/*生成图片*/
		int g = 0, q = 0;
		while (!feof(pfr))
		{
			ch = fgetc(pfr);
			if (g < p + strlen(C))
			{
				if (g % 9 != 0)
				{
					if ((ch & 0x01) && pin[q] == 0)
					{
						ch = ch - 1;
					}
					if (!(ch & 0x01) && pin[q] == 1)
					{
						ch = ch + 1;
					}
					q++;
				}
				g++;
			}
			//printf("%d ", ch);
			fputc(ch, pfw);
		}

		fclose(pfr);
		fclose(pfw);
}

/*移位密码——解密*/
void encryption2(char* name1)
{
	/*打开图片*/
	char C[100] = {'\0'};
	char ch = 0;
	FILE* pfr = fopen(name1, "rb");
	fseek(pfr, 54, SEEK_SET);
	int ans = 0,ki = 0;
	int q = 0;
	int v = 8;
	/*翻译密码*/
	while (1)
	{
		ch = fgetc(pfr);
		if (q % 9 != 0)
		{
			v -= 1;
			ans += (ch & 0x01) * pow(2, v);
		}
		q += 1;
		if (v == 0)
		{
			if ((ans >= 65 && ans <= 90) || (ans >= 97 && ans <= 122))
			{
				C[ki] = ans;
				ki += 1;
				v = 8;
				ans = 0;
			}
			else
				break;
		}
	}
	char M[100];
	int K = 3, i;
	//解密
	for (i = 0; C[i] != '\0'; i++)
	{
		if (C[i] >= 'a' && C[i] <= 'z')
		{
			M[i] = (C[i] - 'a' - K + 26) % 26 + 'a';
		}
		else if (C[i] >= 'A' && C[i] <= 'Z')
		{
			M[i] = (C[i] - 'A' - K + 26) % 26 + 'A';
		}
	}
	M[i] = '\0';
	printf("解密后的明文是:%s\n", M);
}

int main(int argc, char* argv[])
{
	int num;
	myMenu();
	while (1)
	{
		printf("请输入功能编号(1-5):");
		scanf("%d", &num);
		switch (num)
		{
		case 1://直接加密
	        show_bmp("D:\\桌面\\网安实践2—位图信息加密\\风景位图2.bmp", "D:\\桌面\\网安实践2—位图信息加密\\600.bmp");
			break;
	    case 2://直接解密
			get_bmp("D:\\桌面\\网安实践2—位图信息加密\\600.bmp");
			break;
		case 3://二次加密
			encryption1("D:\\桌面\\网安实践2—位图信息加密\\风景位图2.bmp", "D:\\桌面\\网安实践2—位图信息加密\\600.bmp");
			break;
		case 4:
			encryption2("D:\\桌面\\网安实践2—位图信息加密\\600.bmp");
			break;
		case 5:
			printf("已退出系统,感谢您的使用!");
			return 0;
		default:
			printf("输入不正确,应该输入1-5之间的数。\n\n");
			break;
		}
	}
	system("pause");
	return 0;
}

四、测试结果 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值