精华内容
下载资源
问答
  • 走进信息隐藏的世界,全面讲解信息隐藏——第1节:信息隐藏技术简介 专栏题记:奥斯卡优秀电影《美丽心灵》里面有讲述一位优秀数学家为政府破译敌国通讯的情节,如电影所讲,现实中也有着类似的情节,在我们的生活...

    走进信息隐藏的世界,全面讲解信息隐藏——第1节:信息隐藏技术简介


    专栏题记:奥斯卡优秀电影《美丽心灵》里面有讲述一位优秀数学家为政府破译敌国通讯的情节,如电影所讲,现实中也有着类似的情节,在我们的生活中,我们所看过的图片、视频和游览过的网页,也许就隐藏着他人需要传输的秘密信息(是不是有点恐怖,差一点成为帮凶了),这就是信息隐藏!由于应用场景一般比较神秘,导致很多人其实都不太了解信息隐藏技术。由于国家越来越重视网络信息的安全,现在也是有越来越多的研究人员进行着这方面的研究工作。本人也是其中一位非常平凡的研究人员,笔者抱着学习和分享的态度,希望略尽绵薄之力让大家对信息隐藏技术不再陌生,同时慢慢掌握如何进行信息隐藏的技术。接下来本人会不定时更新信息隐藏技术的相关原理和关键技术实现过程,同时会提供程序代码给大家学习,也欢迎有志之士可以和我一同创建学习平台,也可以在评论下建议下一节希望学习的研究内容。谢谢!


    目录

    1、信息隐藏概念

    2、信息隐藏系统模型

    3、信息隐藏技术的分支简介

    4、信息隐藏技术的特性和要求

    5、信息隐藏关键技术

    6、信息隐藏的应用实例

    案例一:信息隐藏技术在电子商务中的应用

    案例二:信息隐藏技术在网络战中的运用



    • 信息隐藏概念

           信息隐藏也称数据隐藏,信息隐藏技术是指在不对载体数据产生可察觉影响的前提下,将密信数据隐藏到载体中实现隐蔽通讯的技术。是集多学科理论与技术于一身的新兴技术领域。信息隐藏技术主要是指将特定的信息嵌入数字化宿主信息(如文本,数字化的声音、图像、视频信号等)中,信息隐藏的目的不在于限制正常的信息存取和访问,而在于保证隐藏的信息不引起监控者的注意和重视,从而减少被攻击的可能性,在此基础上再使用密码术来加强隐藏信息的安全性,因此信息隐藏比信息加密更为安全。应该注意到,密码术和信息隐藏技术不是互相矛盾、互相竞争的技术,而是相互补充的技术,他们的区别在于应用的场合不同,对算法的要求不同,但可能在实际应用中需要互相配合。特定的信息一般就是保密信息,信息隐藏的历史可以追溯到古老的隐写术,但推动了信息隐藏的理论和技术研究始于1996年在剑桥大学召开的国际第一届信息隐藏研究会,之后国际机构在信息隐藏领域中的隐写术、数字水印、版权标识,可视密码学等方面取得大量成果。


    • 信息隐藏系统模型

           广义的信息隐藏系统模型主要有四部分组成:(1)信息嵌入,即利用嵌入秘钥来实现嵌入对象的隐藏过程;(2)信息提取,即利用提取秘钥从隐藏对象或可能经过修改的隐藏对象中提取或恢复出嵌入对象,在提取时,原始的载体对象可能需要参与也可能不需要参与;(3)秘钥生成,根据安全参数生成嵌入秘钥和提取秘钥;(4)隐藏分析,隐藏对象在传输过程中可能会被隐藏分析者截获并进行处理。信息隐藏系统模型如下图所示:

           在信息隐藏系统模型中,在嵌入过程中我们使用嵌入密钥将嵌入对象嵌入掩护对象中,生成隐藏对象,如下图将一个txt的文本嵌入到一张JPEG的图像中。嵌入对象和掩护对象可以是文本、图像或音频等等。在我们没有使用工具进行分析时,我们觉得掩护对象与隐藏对象几乎没有差别,这就是信息隐藏概念中所说的“利用人类感觉器官的不敏感性”。隐藏对象在信道中进行传输,在传输的过程中,有可能会遭到隐藏分析者的攻击,隐藏分析者的目标在于检测出隐藏对象、查明被嵌入对象、向第三方证明消息被嵌入、删除被嵌入对象、阻拦等。其中前三个目标通常可以由被动观察完成,称为被动攻击,后两个目标通常可以由主动攻击实现。提取过程则是在提取密钥的参与下从所接收到的隐藏对象中提取出嵌入对象,如将上述txt文件从JPG的图像中提取出来。有些提取过程并不需要掩护对象的参与,这样的系统称为盲隐藏技术,而需要掩护对象参与的系统则称为非盲隐藏技术。


    • 信息隐藏技术的分支简介

           作为信息安全领域的一个重要组成部分,信息隐藏技术已成为信息安全领域中一个既具有研究价值、同时又极具挑战性的热门课题,信息隐藏技术的分支主要包括:隐写术、数字水印、数字指纹、隐蔽信道、阈下信道、低截获概率通信和匿名通信等等。其分类示意图如下图所示:


    • 信息隐藏技术的特性和要求

           信息隐藏不同于传统的加密,因为其目的不在于限制正常的资料存取,而在于保证隐藏数据不被发现。因此,信息隐藏技术必须考虑正常的信息操作所造成的威胁,即要使机密数据对正常的数据操作技术具有免疫力。根据信息隐藏的不同目的和技术要求,该技术的存在以下特性和要求:

    1. 透明性或不可感知性:利用人类视觉系统或人类听觉系统属性,经过一系列的隐藏处理,使得载体对象没有明显的降质现象,如LSB算法等。当然,有些场合可能需要使用可见水印,例如某些版权维护的场合。
    2. 鲁棒性:指不因隐藏对象通过某些常用操作而导致嵌入对象丢失的能力。这里的常用操作包括滤波操作、有损压缩、几何变换、D/A或A/D等。
    3. 安全性:指算法具有较强的抗恶意攻击能力。
    4. 不可检测性:指载体数据嵌入数据后无明显改变,至少肉眼看不出变化

    • 信息隐藏关键技术

      近年来,信息隐藏技术的研究取得了很大的进步,已经提出了各种各样的隐藏算法。关键的信息隐藏技术有如下几种。

        (1)替换技术

        所谓替换技术,就是试图用秘密信息比特替换掉伪装载体中不重要的部分,以达到对秘密信息进行编码的目的。替换技术包括最低比特位替换、伪随机替换、载体区域的奇偶校验位替换和基于调色板的图像替换等。替换技术是在空间域进行的一种操作,通过选择合适的伪装载体和适当的嵌入区域,能够有效地嵌入秘密信息比特,同时又可保证数据的失真度在人的视觉允许范围内。

        已经提出的各种算法大都给出了其实现思想,如对于基于调色板的图像格式,可操作其调色板来嵌入信息,也可以利用它的量化值来隐藏秘密信息,因此该技术在数据伪装中得到了广泛的应用。

        替换技术算法简单,容易实现,但是鲁棒性很差,不能抵抗图像尺寸变化、压缩等一些基本的攻击,因此在数字水印领域中一般很少使用。

        (2)变换技术

        大部分信息隐藏算法都是在变换域进行的,其变换技术包括离散傅里叶变换(DFT)、离散余弦变换(DFT)、离散小波变换(DWT)和离散哈达玛特变换(DHT)等。这些变换技术都有各自的特点。

        DFT在信号处理中有着广泛应用,在信息隐藏领域也同样得到了应用。它将图像分割成多个感觉频段,然后选择合适部分来嵌入秘密信息。D CT使空间域的能量重新分布,从而降低了图像的相关性。在DCT域中嵌入信息的方法,通常是在一个图像块中调整两个(或多个)DCT系数的相对大小。DWT是对图像的一种多尺度、空间频率分解,即将输入信号分解为低分辨率参考信号和一系列细节信号。在一个尺度下,参考信号和细节信号包含了完全恢复上一尺度下信号的全部信息。

        (3)扩频技术

        当对伪装对象进行过滤操作时可能会消除秘密信息,解决的方法就是重复编码,即扩展隐藏信息。在整个伪装载体中多次嵌入一个比特,使得隐藏信息在过滤后仍能保留下来,这种方法虽然传输效率不高,但却具有较好的健壮性。扩频技术一般是使用比发送的信息数据速率高许多倍的伪随机码,将载有信息数据的基带信号频谱进行扩展,形成宽带低功率谱密度信号。最典型的扩频技术,为直序扩频和跳频扩频。直序扩频是在发端直接用具有高码率的扩频编码去扩展信号的频谱,而在接收端用相同的扩频编码解扩,将扩频信号还原为原始信号。跳频扩频是在发端将信息码序列与扩频码序列组合,然后按照不同的码字去控制频率合成器,使输出频率根据码字的改变而改变,形成频率的跳变;在接收端为了解跳频信号,要用与发端完全相同的本地扩频码发生器去控制本地频率合成器,从中恢复出原始信息


    • 信息隐藏的应用实例

    案例一:信息隐藏技术在电子商务中的应用

      目前信息隐藏技术在电子商务中的应用主要体现在以下几个方面:

      1.数据保密

      在具体电子商务活动中,数据在Internet上进行传输一定要防止非授权用户截获并使用,如敏感信息,谈判双方的秘密协议合同网上银行交易中的敏感数据信息,重要文件的数字签名和个人隐私等等。另外,还可以对一些不愿为别人所知道的内容使用信息隐藏的方式进行隐藏存储。

      2.数据的不可抵赖性

      在网上交易中,交易双方的任何一方不能抵赖自己曾经做出的行为,也不能否认曾经接收到的对方的信息,这是交易系统中的一个重要环节。这可以使用信息隐藏技术中的水印技术,在交易体系的任何一方发送或接收信息时,将各自的特征标记以水印的形式加入到传递的信息中,这咱水印应是不能被去除的,可达到确认其行为的目的。

      3.防伪

      商务活动中的各种票据的防伪也是信息隐藏技术的用武之地。在数字票据中隐藏的水印经过打印后仍然存在,可以通过再扫描回数字形式,提取防伪水印,以证实票据的真实性。

      4.数据的完整性

      对于数据完整性的验证是要确认数据在网上传输或存储过程中并没有被窜改,可通过使用脆弱水印技术保护的媒体一旦被窜改就会破坏水印,从而很容易被识别。

    案例二:信息隐藏技术在网络战中的运用[2]

      信息隐藏之所以比密码加密的方法进行保密通信具有更大优势,是因为以信息隐藏方式实现隐蔽通信,除通信双方以外的任何第三方并不知道秘密通信这个事实的存在,这就较之单纯的密码加密更多了一层保护,使得网络加密机制从“看不懂”变为“看不见”,以不至成为好事者攻击的目标。

      (1)数据保密

      在因特网上防止非授权用户截获并使用传输的一些秘密数据,是网络安全的一个重要内容。信息隐藏技术在军事上的应用,可以将一些不愿为人所知的重要标识信息用信息隐藏的方式进行隐蔽存储,像军事地图中标明的军备部署、打击目标,卫星遥感图像的拍摄日期、经纬度等等,都可用隐藏标记的方法使其以不可见的形式隐藏起来,只有掌握识别软件的人才能读出标记所在。

      (2)数据保护

      数据保护主要是保证传输信息的完整性。由于隐藏的信息是被藏在宿主图像等媒体的内容中,而不是文件头等处,因而不会因格式的变换而遭到破坏。同时隐藏的信息具有很强的对抗非法探测和非法破解的能力,可以对数据起到安全保护的作用。对于数据完整性的验证是要确认数据在网上传输或存储过程中并没有被窜改。通过使用脆弱水印技术保护的媒体一旦被窜改就会破坏水印,从而很容易被识别。

      (3)数据免疫

      所谓免疫是指不因宿主文件经历了某些变化或处理而导致隐藏信息丢失的能力。某些变化和处理包括:传输过程中的信道噪声干扰,过滤操作,再取样,再量化,数/模、模/数转换,无损、有损压缩,剪切,位移等。


    作者:Daniel
    来源:CSDN 
    版权声明:本文为原创文章,转载请附上博文链接:
    https://blog.csdn.net/qq_26464039/article/details/85779870


    展开全文
  • 信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是透明的。传统的信息隐藏起源于古老的隐写术。如在古希腊战争中,为了安全地传送军事情报,奴隶主...

    信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是透明的。

    传统的信息隐藏起源于古老的隐写术。如在古希腊战争中,为了安全地传送军事情报,奴隶主剃光奴隶 的头发,将情报文在奴隶的头皮上,待头发长起后再派出去传送消息。我国古代也早有以藏头诗、藏尾诗、漏格诗以及绘画等形式,将要表达的意思和“密语”隐藏在诗文或画卷中的特定位置,一般人只注意诗或画的表面意境,而不会去注意或破解隐藏其中的密语。   信息隐藏的发展历史可以一直追溯到"匿形术(Steganography)"的使用。"匿形术"一词来源于古希腊文中"隐藏的"和"图形"两个词语的组合。虽然"匿形术"与"密码术(Cryptography)"都是致力于信息的保密技术,但是,两者的设计思想却完全不同。"密码术"主要通过设计加密技术,使保密信息不可读,但是对于非授权者来讲,虽然他无法获知保密信息的具体内容,却能意识到保密信息的存在。而"匿形术"则致力于通过设计精妙的方法,使得非授权者根本无从得知保密信息的存在与否。相对于现代密码学来讲,信息隐藏的最大优势在于它并不限制对主信号的存取和访问,而是致力于签字信号的安全保密性。

     

     

    我们进行信息交换的时候,需要保证数据的安全,所以需要进行适当的信息隐藏。

    我们发送一个图片。但是图片里面隐含的加密信息,是就是信息隐藏,只有专属工具能够读出。

    所以信息隐藏技术很重要。针对信息安全。

    我们来实现一个案例代码。

    BMP图信息隐藏头文件,请见代码分析

    // BMPHider.h: interface for the CBMPHider class.
    //
    //
    
    #if !defined(AFX_BMPHIDER_H__6287D87F_F0AA_4D0C_9502_4674B639CBB5__INCLUDED_)
    #define AFX_BMPHIDER_H__6287D87F_F0AA_4D0C_9502_4674B639CBB5__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    #include <complex>
    using namespace std;
    class CBMPHider  
    {
    public:
    	CBMPHider();
    	virtual ~CBMPHider();
    public:
    	int m_BitCount;			//位图的图像位数
    	WORD * m_pWordData;
    	CPalette m_Palette;
    	unsigned char *m_pDib, *m_pDibBits;
    	unsigned char *m_pOldDibShow;
    	DWORD m_dwDibSize;
    	BITMAPINFOHEADER *m_pBIH;
    	RGBQUAD *m_pPalette;
    	int m_nPaletteEntries;
    	UINT bitmap_size;
    	UINT embfile_size;
    	unsigned char *p;		//指向宿主图像数据
    	int tag;				//此tag用以标记打开的图像中是否含有隐藏信息0:无 else:有
    	unsigned char *q;		//指向隐藏文件数据
    	unsigned char *m_pFile;
    public:
    	BOOL Draw( CDC *pDC, int nX = -1, int nY = -1, int nWidth = -1, int nHeight = -1, int Style = 1);
    	BOOL Save( const char *pszFilename );
    	BOOL Load( const char * );
    	
    	void BackUpDib();		//备份图像
    	void Pick();			//提取图像
    	void Embed();			//嵌入图像
    	BOOL LoadEmbFile(const char *);
    	BOOL DrawContrast(CDC *pDC,int rect_width, int rect_height);
    	void SavePicked( const char *pszFilename );	
    
    };
    
    #endif // !defined(AFX_BMPHIDER_H__6287D87F_F0AA_4D0C_9502_4674B639CBB5__INCLUDED_)


    请见详细代码实现

     

    #include "stdafx.h"
    #include "BMPHider.h"
    
    //
    // Construction/Destruction
    //
    
    CBMPHider::CBMPHider()
    {
    	m_pDib = NULL;
    	m_pWordData = NULL;
    	m_pFile = NULL;
    	m_pOldDibShow = NULL;
    }
    
    CBMPHider::~CBMPHider()
    {
    	if( m_pDib != NULL )
    		delete [] m_pDib;
    	if( m_pWordData != NULL )
    		delete [] m_pWordData;
    	if (m_pFile != NULL)
    		delete [] m_pFile;
    	if (m_pOldDibShow != NULL)
    		delete [] m_pOldDibShow;
    }
    
    BOOL CBMPHider::Load( const char *pszFilename )
    {
    	CFile cf;
    	if( !cf.Open( pszFilename, CFile::modeRead ) )
    		return( FALSE );
    	
    	DWORD dwDibSize;
    	dwDibSize =
    		cf.GetLength() - sizeof( BITMAPFILEHEADER );
    
    	unsigned char *pDib;
    	pDib = new unsigned char [dwDibSize];
    	if( pDib == NULL )
    		return( FALSE );
    
    	BITMAPFILEHEADER BFH;
    	try
    	{
    		if( cf.Read( &BFH, sizeof( BITMAPFILEHEADER ) )
    			!= sizeof( BITMAPFILEHEADER ) ||
    			BFH.bfType != 'MB' ||
    			cf.Read( pDib, dwDibSize ) != dwDibSize )
    		{
    			delete [] pDib;
    			return( FALSE );
    		}
    	}
    	
    	catch( CFileException *e )
    	{
    		e->Delete();
    		delete [] pDib;
    		return( FALSE );
    	}
    	cf.Close();
    	if( m_pDib != NULL )
    		delete m_pDib;
    	if (BFH.bfReserved1 != 0)          //含有隐藏信息,保存其大小
    	{
    		if (BFH.bfReserved2 == 0)
    			embfile_size = BFH.bfReserved1;
    		else
    			embfile_size = BFH.bfReserved1 + 65535;
    	}
    	m_pDib = pDib;
    	m_dwDibSize = dwDibSize;
    	m_pBIH = (BITMAPINFOHEADER *) m_pDib;
    	m_pPalette =(RGBQUAD *) &m_pDib[sizeof(BITMAPINFOHEADER)];
    	m_nPaletteEntries = 1 << m_pBIH->biBitCount;
    	if( m_pBIH->biBitCount > 8 )         
    		m_nPaletteEntries = 0;
    	else if( m_pBIH->biClrUsed != 0 )
    		m_nPaletteEntries = m_pBIH->biClrUsed;
    	m_pDibBits = &m_pDib[sizeof(BITMAPINFOHEADER)+
    			m_nPaletteEntries*sizeof(RGBQUAD)];
    
    	if( m_Palette.GetSafeHandle() != NULL )
    		m_Palette.DeleteObject();
    
    	if( m_nPaletteEntries != 0 )
    	{      
    
    		LOGPALETTE *pLogPal = (LOGPALETTE *) new char
    				[sizeof(LOGPALETTE)+
    				m_nPaletteEntries*sizeof(PALETTEENTRY)];
    
    		if( pLogPal != NULL )
    		{
    			pLogPal->palVersion = 0x300;
    			pLogPal->palNumEntries = m_nPaletteEntries;
    
    			for( int i=0; i<m_nPaletteEntries; i++ )
    			{
    				pLogPal->palPalEntry[i].peRed =
    					m_pPalette[i].rgbRed;
    				pLogPal->palPalEntry[i].peGreen =
    					m_pPalette[i].rgbGreen;
    				pLogPal->palPalEntry[i].peBlue =
    					m_pPalette[i].rgbBlue;
    			}
    
    			m_Palette.CreatePalette( pLogPal );
    			delete [] pLogPal;
    		}
    	}
    
    	m_BitCount = 24;             //24位位图
    	p = m_pDibBits;              //指向位图数据的指针,用来执行处理操作用
    	bitmap_size = m_dwDibSize - (m_pDibBits - m_pDib);//真正的位图数据的大小(即除头结构外)
    	
    	tag = BFH.bfReserved1;
    	return( TRUE );
    
    }
    
    BOOL CBMPHider::Save( const char *pszFilename ) //保存含有隐藏信息的bmp
    {
    	if( m_pDib == NULL )
    		return( FALSE );
    	CFile cf;
    	if( !cf.Open( pszFilename,
    		CFile::modeCreate | CFile::modeWrite ) )
    		return( FALSE );
    	try
    	{
    		BITMAPFILEHEADER BFH;
    		memset( &BFH, 0, sizeof( BITMAPFILEHEADER ) );
    		BFH.bfType = 'MB';
    		BFH.bfSize = sizeof( BITMAPFILEHEADER ) + m_dwDibSize;
    		BFH.bfOffBits = sizeof( BITMAPFILEHEADER ) +
    			sizeof( BITMAPINFOHEADER ) +
    			m_nPaletteEntries * sizeof( RGBQUAD );
    		if (embfile_size <= 65535)   
    			//由于bfReserved1是unsigned short型的,大小可能不能满足要求,可能要用到reserved2
    			BFH.bfReserved1 = embfile_size;   
    		else
    		{
    			BFH.bfReserved1 = embfile_size - 65535;
    			BFH.bfReserved2 = 1; //标记
    		}
    		cf.Write( &BFH, sizeof( BITMAPFILEHEADER ) );
    		cf.Write( m_pDib, m_dwDibSize );
    	}
    	catch( CFileException *e )
    	{
    		e->Delete();
    		return( FALSE );
    	}
    	return( TRUE );
    }
    
    BOOL CBMPHider::Draw( CDC *pDC, int nX, int nY, int nWidth, int nHeight, int Style )
    {
     	if( m_pDib == NULL )
    		return( FALSE );
     	long vWidth = m_pBIH->biWidth;
     	if( nWidth == -1 )
     		nWidth = m_pBIH->biWidth;
    	if( nHeight == -1 )
     		nHeight = m_pBIH->biHeight;
     	if (Style)   
     	{
     		StretchDIBits( pDC->m_hDC, nX, nY,
     			nWidth, nHeight,
     			0, 0,
     			m_pBIH->biWidth, m_pBIH->biHeight,
     			m_pDibBits,
     			(BITMAPINFO *) m_pBIH,
    			BI_RGB, SRCCOPY );
     	}
     	else
     	{
    		SetDIBitsToDevice( pDC->m_hDC, nX, nY,
     			m_pBIH->biWidth, m_pBIH->biHeight,
    			0, 0,
     			0, m_pBIH->biHeight,
     			m_pDibBits,
     			(BITMAPINFO *) m_pBIH,
     			BI_RGB);
     	}
    	return( TRUE );
    }
    
    
    
    BOOL CBMPHider::LoadEmbFile(const char * pszFilename)
    {	
    	CFile cf;
    	if( !cf.Open( pszFilename, CFile::modeRead ) )
    		return( FALSE );
    
    	DWORD dwFileSize;
    	dwFileSize = cf.GetLength();
    
    	embfile_size = dwFileSize;
    	unsigned char *pFile;
    	pFile = new unsigned char [dwFileSize];
    	cf.Read( pFile, dwFileSize );       //将文件中内容读入数组,解下来就开始嵌入操作
    
    	m_pFile = pFile;
    	q = pFile;        //记录下位置
    	return true;
    }
    
    void CBMPHider::Embed()//嵌入
    {
    	unsigned char bmdata;//bitmap data
    	unsigned char efdata;//embeddedfile data
    	int t = 7;		
    	int x[8];	
    	int s[8];
    	int last_bit; //记录字节最低位本来的bit
    
    	for(UINT i1 = 0, i2 = 0; i1 <= bitmap_size - 1, i2 <= embfile_size - 1; i1++)
    	{
    		bmdata = *p;
    
    		for (int j = 0; j <= 7; j++) //计算各bit位
    		{
    			x[j] = bmdata & 1;
    			bmdata >>= 1;
    		}
    		
    		last_bit = x[0];
    		x[0] = x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7];
    		
    		if (t == 7)    //宿主图片每走过八个字节,计算一次s[]
    		{
    			efdata = *q;
    			for (j = 0; j <= 7; j++)
    			{
    				s[j] = efdata & 1;
    				efdata >>= 1;
    			}
    		}
    		x[0] ^= s[t];//隐藏信息
    		if (last_bit == 0)  //嵌入隐藏信息
    		{
    			*p |= x[0];
    		}
    		else
    		{
    			*p &= 254 + x[0];
    		}
    	
    		p++;
    		t--;
    		if (t == -1)  //需要计算一次s[]
    		{
    			t = 7;
    			q++;
    			i2++;
    		}
    	}
    
    }
    
    void CBMPHider::Pick()//提取
    {
    	m_pFile = new unsigned char [embfile_size];
    	unsigned char *q = m_pFile;
    
    	unsigned char bmdata;//bitmap data
    
    	int x[8];	
    	int s[8];
    	int t = 7;
    	for (UINT i1 = 0, i2 = 0; i1 <= bitmap_size - 1, i2 <= embfile_size - 1; i1++)
    	{
    		bmdata = *p;
    		for (int j = 0; j <= 7; j++) //计算各bit位
    		{
    			x[j] = bmdata & 1;
    			bmdata >>= 1;
    		}
    		s[t] = x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7];
    		t--;
    		if (t == -1) //s[7]到s[0]组成一个字节
    		{
    			*q = s[7] * 128 + s[6] * 64 + s[5] * 32 + s[4] * 16 + 
    				s[3] * 8 + s[2] * 4 + s[1] * 2 + s[0];
    			t = 7;
    			i2++;
    			q++;
    		}
    		p++;
    	}
    
    }
    	
    void CBMPHider::SavePicked( const char *pszFilename )
    {
    	CFile cf;
    	cf.Open( pszFilename, CFile::modeCreate | CFile::modeWrite );
    	cf.Write( m_pFile, embfile_size );
    }
    
    void CBMPHider::BackUpDib()
    {
    	m_pOldDibShow = new unsigned char [bitmap_size];
       
    	::CopyMemory(m_pOldDibShow, m_pDibBits, bitmap_size); //将原始的数据单独保存以便对比显示
    }
    
    BOOL CBMPHider::DrawContrast(CDC *pDC, int rect_width, int rect_height)
    {                             //看原图,如果容纳得下两个图,则不要压缩,否则要压缩
    	if (m_pOldDibShow == NULL)
    		return FALSE;
    	if (rect_width >= 2*m_pBIH->biWidth + 30 && rect_height >= m_pBIH->biHeight)
    	{
    		StretchDIBits( pDC->m_hDC, 0, 0,
    		m_pBIH->biWidth, m_pBIH->biHeight,
    		0, 0,
    		m_pBIH->biWidth, m_pBIH->biHeight,
    		m_pOldDibShow,
    		(BITMAPINFO *) m_pBIH,
    		BI_RGB, SRCCOPY );    // 原图
    
    		StretchDIBits( pDC->m_hDC, m_pBIH->biWidth+30, 0,
    		m_pBIH->biWidth, m_pBIH->biHeight,
    		0, 0,
    		m_pBIH->biWidth, m_pBIH->biHeight,
    		m_pDibBits,
    		(BITMAPINFO *) m_pBIH,
    		BI_RGB, SRCCOPY );    // 嵌入隐藏信息的图
    	}
    	else
    	{
    		int scale_i = m_pBIH->biWidth * 5 / (rect_width*2);
    		int scale_j = m_pBIH->biHeight / rect_height;
    		if (scale_i < scale_j)
    			scale_i = scale_j;
    
    		StretchDIBits( pDC->m_hDC, 0, 0,
    		m_pBIH->biWidth / scale_i, m_pBIH->biHeight / scale_i,
    		0, 0,
    		m_pBIH->biWidth, m_pBIH->biHeight,
    		m_pOldDibShow,
    		(BITMAPINFO *) m_pBIH,
    		BI_RGB, SRCCOPY );    // 原图
    
    		StretchDIBits( pDC->m_hDC, m_pBIH->biWidth / scale_i+30, 0,
    		m_pBIH->biWidth / scale_i, m_pBIH->biHeight / scale_i,
    		0, 0,
    		m_pBIH->biWidth, m_pBIH->biHeight,
    		m_pDibBits,
    		(BITMAPINFO *) m_pBIH,
    		BI_RGB, SRCCOPY );    // 嵌入隐藏信息的图
    
    	}
    
    	return TRUE;
    }


    具体代码调用实现

    #include "stdafx.h"
    #include "DataHideInBMP.h"
    
    #include "DataHideInBMPDoc.h"
    #include "DataHideInBMPView.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /
    // CDataHideInBMPView
    
    IMPLEMENT_DYNCREATE(CDataHideInBMPView, CView)
    
    BEGIN_MESSAGE_MAP(CDataHideInBMPView, CView)
    	//{{AFX_MSG_MAP(CDataHideInBMPView)
    	ON_COMMAND(ID_NORMAL, OnNormal)
    	ON_COMMAND(ID_STRETCH, OnStretch)
    	ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
    	ON_COMMAND(ID_EMBED, OnEmbed)
    	ON_UPDATE_COMMAND_UI(ID_EMBED, OnUpdateEmbed)
    	ON_COMMAND(ID_PICK, OnPick)
    	ON_UPDATE_COMMAND_UI(ID_PICK, OnUpdatePick)
    	//}}AFX_MSG_MAP
    	// Standard printing commands
    	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
    	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
    	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
    END_MESSAGE_MAP()
    
    /
    // CDataHideInBMPView construction/destruction
    
    CDataHideInBMPView::CDataHideInBMPView()
    {
    	// TODO: add construction code here
    	ImageStyle = 0;
        have_open_a_file = false;
    
    	embed = false;
    	pick = false;
    	show_contrast = false;
    }
    
    CDataHideInBMPView::~CDataHideInBMPView()
    {
    }
    
    BOOL CDataHideInBMPView::PreCreateWindow(CREATESTRUCT& cs)
    {
    	// TODO: Modify the Window class or styles here by modifying
    	//  the CREATESTRUCT cs
    	WNDCLASSEX wndcls;
    	wndcls.cbSize=sizeof(WNDCLASSEX);
    	HINSTANCE hinst=AfxGetInstanceHandle();
    	if(CView::PreCreateWindow(cs)&&cs.lpszClass!=NULL)
    	{
    		HBRUSH hbkbrush=CreateSolidBrush(RGB(0,0,0));
    		if(!GetClassInfoEx(hinst,cs.lpszClass,&wndcls))
    			return FALSE;
    		UnregisterClass(cs.lpszClass,hinst);
    		wndcls.hbrBackground=hbkbrush;
    		RegisterClassEx(&wndcls);  
    		return TRUE;
    	}
    	else
    		return FALSE;
    	return CView::PreCreateWindow(cs);
    }
    
    /
    // CDataHideInBMPView drawing
    
    void CDataHideInBMPView::OnDraw(CDC* pDC)
    {
    	CDataHideInBMPDoc* pDoc = GetDocument();
    	ASSERT_VALID(pDoc);
    	// TODO: add draw code for native data here
    	RECT Rect;
    	GetClientRect( &Rect );
    
    	if (!show_contrast)
    		m_BMPHider.Draw( pDC, 0, 0, Rect.right, Rect.bottom, ImageStyle );
    	else
    	{
    		m_BMPHider.DrawContrast(pDC, Rect.right, Rect.bottom);
    		pDC->SetBkColor((0,0,0));
    		pDC->SetTextColor((255,255,255));
    		pDC->TextOut(0, Rect.bottom-30, "左图为原始图,右图为嵌入了隐藏信息的图");
    	}
    }
    
    /
    // CDataHideInBMPView printing
    
    BOOL CDataHideInBMPView::OnPreparePrinting(CPrintInfo* pInfo)
    {
    	// default preparation
    	return DoPreparePrinting(pInfo);
    }
    
    void CDataHideInBMPView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
    {
    	// TODO: add extra initialization before printing
    }
    
    void CDataHideInBMPView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
    {
    	// TODO: add cleanup after printing
    }
    
    /
    // CDataHideInBMPView diagnostics
    
    #ifdef _DEBUG
    void CDataHideInBMPView::AssertValid() const
    {
    	CView::AssertValid();
    }
    
    void CDataHideInBMPView::Dump(CDumpContext& dc) const
    {
    	CView::Dump(dc);
    }
    
    CDataHideInBMPDoc* CDataHideInBMPView::GetDocument() // non-debug version is inline
    {
    	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDataHideInBMPDoc)));
    	return (CDataHideInBMPDoc*)m_pDocument;
    }
    #endif //_DEBUG
    
    /
    // CDataHideInBMPView message handlers
    
    void CDataHideInBMPView::OnNormal() 
    {
    	// TODO: Add your command handler code here
    	ImageStyle = 0;
    
    	CMenu *pMnu = AfxGetMainWnd()->GetMenu( );
    	pMnu->CheckMenuItem(ID_STRETCH,MF_UNCHECKED);
    	pMnu->CheckMenuItem(ID_NORMAL,MF_CHECKED);
    	
    	InvalidateRect( NULL, TRUE );
    	UpdateWindow();	
    }
    
    void CDataHideInBMPView::OnStretch() 
    {
    	// TODO: Add your command handler code here
    	ImageStyle = 1;
    	
    	CMenu *pMnu = AfxGetMainWnd()->GetMenu( );
    	pMnu->CheckMenuItem(ID_STRETCH,MF_CHECKED);
    	pMnu->CheckMenuItem(ID_NORMAL,MF_UNCHECKED);
    	
    	InvalidateRect( NULL, TRUE );
    	UpdateWindow();	
    }
    
    void CDataHideInBMPView::OnFileOpen() 
    {
    	// TODO: Add your command handler code here
    	show_contrast = false;   //非对比显示
    	static char szFilter[] = "BMP Files(*.BMP)|*.BMP||";
    
    	CFileDialog FileDlg( TRUE, NULL, NULL,
    		OFN_HIDEREADONLY, szFilter );
    
    	if( FileDlg.DoModal() == IDOK &&
    		m_BMPHider.Load( FileDlg.GetPathName() ) )
    	{
    		InvalidateRect( NULL, TRUE );
    		UpdateWindow();
    		have_open_a_file=true;
    		if (m_BMPHider.tag == 0)//该图无隐藏信息
    		{
    			embed = true;
    			pick = false;  //菜单亮暗控制
    		}//
    		else
    		{
    			embed = false;
    			pick = true;  //菜单亮暗控制
    		}//
    	}	
    }
    
    void CDataHideInBMPView::OnEmbed() 
    {
    	// TODO: Add your command handler code here
    	//弹出打开对话框,用户选择嵌入的文件
    
    	static char szFilter[] = "All Files(*.*)|*.*||";
    
    	CFileDialog FileDlg( TRUE, NULL, NULL,
    		OFN_HIDEREADONLY, szFilter );
    
    	if( FileDlg.DoModal() == IDOK &&
    		m_BMPHider.LoadEmbFile( FileDlg.GetPathName() ) )
    	{ 
    		if (m_BMPHider.bitmap_size / m_BMPHider.embfile_size < 8)
    		{
    			AfxMessageBox("文件太大,无法嵌入!");
    		}
    		else
    		{
    			show_contrast = true;
    			m_BMPHider.BackUpDib(); //图片原始数据备份供对比显示
    			m_BMPHider.Embed();   //嵌入
    			
    			Invalidate(true);//刷屏,显示加入隐藏信息后的图像
    			
    			static char szFilter[] = "BMP Files(*.BMP)|*.BMP||";
    			CFileDialog FileDlg( FALSE, "bmp", NULL,                //保存
    				OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, szFilter );
    			
    			if( FileDlg.DoModal() == IDOK )
    			{
    				m_BMPHider.Save( FileDlg.GetPathName() );
    			}
    			embed = false;
    		}
    		
    	}	
    }
    
    void CDataHideInBMPView::OnUpdateEmbed(CCmdUI* pCmdUI) 
    {
    	// TODO: Add your command update UI handler code here
    	pCmdUI->Enable(embed);	
    }
    
    void CDataHideInBMPView::OnPick() 
    {
    	// TODO: Add your command handler code here
    	//提取完毕,弹出保存对话框,用户进行保存
    	static char szFilter[] = "All Files(*.*)|*.*||";
    	CFileDialog FileDlg( FALSE, "", NULL,                //保存
    		OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, szFilter );
    				
    	if (FileDlg.DoModal() == IDOK)
    	{	
    		m_BMPHider.Pick();
    		m_BMPHider.SavePicked(FileDlg.GetPathName());
    		pick = false;
    	}	
    }
    
    void CDataHideInBMPView::OnUpdatePick(CCmdUI* pCmdUI) 
    {
    	// TODO: Add your command update UI handler code here
    	pCmdUI->Enable(pick);	
    }
    


     

    展开全文
  • 信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是透明的。传统的信息隐藏起源于古老的隐写术。如在古希腊战争中,为了安全地传送军事情报,奴隶主...

    信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是透明的。

    传统的信息隐藏起源于古老的隐写术。如在古希腊战争中,为了安全地传送军事情报,奴隶主剃光奴隶 的头发,将情报文在奴隶的头皮上,待头发长起后再派出去传送消息。我国古代也早有以藏头诗、藏尾诗、漏格诗以及绘画等形式,将要表达的意思和“密语”隐藏在诗文或画卷中的特定位置,一般人只注意诗或画的表面意境,而不会去注意或破解隐藏其中的密语。   信息隐藏的发展历史可以一直追溯到"匿形术(Steganography)"的使用。"匿形术"一词来源于古希腊文中"隐藏的"和"图形"两个词语的组合。虽然"匿形术"与"密码术(Cryptography)"都是致力于信息的保密技术,但是,两者的设计思想却完全不同。"密码术"主要通过设计加密技术,使保密信息不可读,但是对于非授权者来讲,虽然他无法获知保密信息的具体内容,却能意识到保密信息的存在。而"匿形术"则致力于通过设计精妙的方法,使得非授权者根本无从得知保密信息的存在与否。相对于现代密码学来讲,信息隐藏的最大优势在于它并不限制对主信号的存取和访问,而是致力于签字信号的安全保密性。

    我们来实践一个基于一阶Bézier曲线的信息隐藏编程实例 ,需要一定的数学基础,请见代码分析。

     

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /
    // CAboutDlg dialog used for App About
    
    class CAboutDlg : public CDialog
    {
    public:
    	CAboutDlg();
    
    // Dialog Data
    	//{{AFX_DATA(CAboutDlg)
    	enum { IDD = IDD_ABOUTBOX };
    	//}}AFX_DATA
    
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CAboutDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL
    
    // Implementation
    protected:
    	//{{AFX_MSG(CAboutDlg)
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    	//{{AFX_DATA_INIT(CAboutDlg)
    	//}}AFX_DATA_INIT
    }
    
    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CAboutDlg)
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    	//{{AFX_MSG_MAP(CAboutDlg)
    		// No message handlers
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /
    // CDataHideInBMPBZDlg dialog
    
    CDataHideInBMPBZDlg::CDataHideInBMPBZDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CDataHideInBMPBZDlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CDataHideInBMPBZDlg)
    		// NOTE: the ClassWizard will add member initialization here
    	//}}AFX_DATA_INIT
    	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
    
    void CDataHideInBMPBZDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CDataHideInBMPBZDlg)
    		// NOTE: the ClassWizard will add DDX and DDV calls here
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CDataHideInBMPBZDlg, CDialog)
    	//{{AFX_MSG_MAP(CDataHideInBMPBZDlg)
    	ON_WM_SYSCOMMAND()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	ON_BN_CLICKED(IDC_BASEBMP_HIDE, OnBasebmpHide)
    	ON_BN_CLICKED(IDC_HIDEFILE, OnHidefile)
    	ON_BN_CLICKED(IDC_DOHIDE, OnDohide)
    	ON_BN_CLICKED(IDC_BASEBMP_RESUME, OnBasebmpResume)
    	ON_BN_CLICKED(IDC_BASEFILE, OnBasefile)
    	ON_BN_CLICKED(IDC_RESUMEDATA, OnResumedata)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /
    // CDataHideInBMPBZDlg message handlers
    
    BOOL CDataHideInBMPBZDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Add "About..." menu item to system menu.
    
    	// IDM_ABOUTBOX must be in the system command range.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		CString strAboutMenu;
    		strAboutMenu.LoadString(IDS_ABOUTBOX);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    	
    	// TODO: Add extra initialization here
    	t=0.035;		//融合系数
    	m_bBaseBMPHide=false;
    	m_bBaseBMPResume=false;
    	m_bHidefile=false;
    	m_bBasefile=false;
    	GetDlgItem(IDC_DOHIDE)->EnableWindow(m_bBaseBMPHide && m_bHidefile);
    	GetDlgItem(IDC_RESUMEDATA)->EnableWindow(m_bBaseBMPResume && m_bBasefile);
    
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    
    void CDataHideInBMPBZDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    	{
    		CAboutDlg dlgAbout;
    		dlgAbout.DoModal();
    	}
    	else
    	{
    		CDialog::OnSysCommand(nID, lParam);
    	}
    }
    
    // If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.
    
    void CDataHideInBMPBZDlg::OnPaint() 
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // device context for painting
    
    		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
    
    		// Center icon in client rectangle
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// Draw the icon
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialog::OnPaint();
    	}
    }
    
    // The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CDataHideInBMPBZDlg::OnQueryDragIcon()
    {
    	return (HCURSOR) m_hIcon;
    }
    
    unsigned char CDataHideInBMPBZDlg::HideCalculate(unsigned char B, unsigned char H)
    {
    	unsigned char R=(int)((1-t)*B+0.5f)+(int)(t*H+0.5f);
    	return R;
    }
    
    unsigned char CDataHideInBMPBZDlg::ShowCalculate(unsigned char C, unsigned char B)
    {
    	unsigned char R=(int)((C- (int)((1-t)*B+0.5f))/t+0.5f);
    	if(R%32>15)
    		R+=15;
    	R=(int)(R/32.0f+0.5f);
    	return R;
    }
    
    
    void CDataHideInBMPBZDlg::OnBasebmpHide() 
    {
    	// TODO: Add your control notification handler code here
    	CFileDialog dlg(TRUE,"bmp","*.bmp",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"载体位图文件(*.bmp)|*.bmp||",NULL);
    	if(dlg.DoModal()==IDOK)
    	{
    		m_bBaseBMPHide=true;
    		m_sCarrierFileHide=dlg.GetPathName();
    		GetDlgItem(IDC_BASEBMP_HIDE)->SetWindowText(m_sCarrierFileHide);
    	}
    	else
    		m_bBaseBMPHide=false;
    	GetDlgItem(IDC_DOHIDE)->EnableWindow(m_bBaseBMPHide && m_bHidefile);
    }
    
    void CDataHideInBMPBZDlg::OnHidefile() 
    {
    	// TODO: Add your control notification handler code here
    	CFileDialog dlg(TRUE,"*","*.*",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"待隐藏文件(*.*)|*.*||",NULL);
    	if(dlg.DoModal()==IDOK)
    	{
    		m_bHidefile=true;
    		m_sHideFile=dlg.GetPathName();
    		m_sHideFileName=dlg.GetFileName();
    		GetDlgItem(IDC_HIDEFILE)->SetWindowText(m_sHideFileName);
    	}
    	else
    		m_bHidefile=false;
    	GetDlgItem(IDC_DOHIDE)->EnableWindow(m_bBaseBMPHide && m_bHidefile);
    }
    
    void CDataHideInBMPBZDlg::OnDohide() 
    {
    	// TODO: Add your control notification handler code here
    	CFile BaseFile,HideFile;
    	DWORD BaseFileLen,HideFileLen;
    	
    	unsigned char* BaseData;
    	unsigned char* HideData;
    
    	
    	if(m_bBaseBMPHide==true && m_bHidefile==true)
    	{
    		BaseFile.Open(m_sCarrierFileHide,CFile::modeReadWrite);
    		BaseFileLen=BaseFile.GetLength();
    		HideFile.Open(m_sHideFile,CFile::modeReadWrite);
    		HideFileLen=HideFile.GetLength();
    		
    		//信息头:文件名*文件长*
    		CString	InfoHead;
    		InfoHead.Format("%s*%d*",m_sHideFileName,HideFileLen);
    		int HeadLen=InfoHead.GetLength();
    		
    		if(BaseFileLen<((HeadLen+HideFileLen)*8)/3+100)
    		{
    			AfxMessageBox("待隐藏文件过大!请换一较大载体位图文件。");
    			return;
    		}
    
    		BaseData=new unsigned char[BaseFileLen];
    		BaseFile.Read(BaseData,BaseFileLen);
    		HideData=new unsigned char[BaseFileLen];
    		//对明文进行组帧
    		for(int k=0;k<HeadLen;k++)
    			HideData[k]=InfoHead.GetAt(k);
    		HideFile.Read(HideData+HeadLen,HideFileLen);
    		for(DWORD kk=HeadLen+HideFileLen;kk<BaseFileLen;kk++)
    			HideData[kk]=0;
    
    		if(BaseData[28]!=24)
    		{
    			AfxMessageBox("载体文件格式错误!");
    			BaseFile.Close();
    			if(BaseData!=NULL)
    				delete BaseData;
    			return;
    		}
    		unsigned char Temp=0;
    		DWORD j=0;
    		for(DWORD i=54;i<BaseFileLen;i++)
    		{
    			Temp=((HideData[j]&224)>>5)<<5;		//1
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			i++;
    			Temp=((HideData[j]&28)>>2)<<5;		//2
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			i++;
    			Temp=(HideData[j]&3)<<1;			//3
    			j++;
    			Temp|=(HideData[j]&128)>>7;
    			Temp*=32;
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			i++;
    			Temp=((HideData[j]&112)>>4)<<5;		//4
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			i++;
    			Temp=((HideData[j]&14)>>1)<<5;		//5
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			i++;
    			Temp=(HideData[j]&1)<<2;			//6
    			j++;
    			Temp|=(HideData[j]&192)>>6;
    			Temp*=32;
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			i++;
    			Temp=((HideData[j]&56)>>3)<<5;		//7
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			i++;
    			Temp=(HideData[j]&7)<<5;			//8
    			BaseData[i]=HideCalculate(BaseData[i],Temp);
    			j++;
    		}
    
    		BaseFile.Close();
    		HideFile.Close();
    		
    		CFile file;
    		file.Open("融合图像.bmp",CFile::modeCreate|CFile::modeReadWrite);
    		file.Write(BaseData,BaseFileLen);
    		file.Close();
    		AfxMessageBox("信息隐藏完毕!");
    		
    		if(BaseData!=NULL)
    			delete BaseData;
    		if(HideData!=NULL)
    			delete HideData;
    	}		
    }
    
    void CDataHideInBMPBZDlg::OnBasebmpResume() 
    {
    	// TODO: Add your control notification handler code here
    	CFileDialog dlg(TRUE,"bmp","*.bmp",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"载体位图文件(*.bmp)|*.bmp||",NULL);
    	if(dlg.DoModal()==IDOK)
    	{
    		m_bBaseBMPResume=true;
    		m_sCarrierFileResume=dlg.GetPathName();
    		GetDlgItem(IDC_BASEBMP_RESUME)->SetWindowText(m_sCarrierFileResume);
    
    	}
    	else
    		m_bBaseBMPResume=false;
    	GetDlgItem(IDC_RESUMEDATA)->EnableWindow(m_bBaseBMPResume && m_bBasefile);
    }
    
    void CDataHideInBMPBZDlg::OnBasefile() 
    {
    	// TODO: Add your control notification handler code here
    	CFileDialog dlg(TRUE,"bmp","*.bmp",OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"原始文件(*.bmp)|*.bmp||",NULL);
    	if(dlg.DoModal()==IDOK)
    	{
    		m_bBasefile=true;
    		m_sBaseFile=dlg.GetPathName();
    		GetDlgItem(IDC_BASEFILE)->SetWindowText(m_sBaseFile);
    	}
    	else
    		m_bBasefile=false;
    	GetDlgItem(IDC_RESUMEDATA)->EnableWindow(m_bBaseBMPResume && m_bBasefile);
    }
    
    void CDataHideInBMPBZDlg::OnResumedata() 
    {
    	// TODO: Add your control notification handler code here
    	CFile BaseFile;
    	CFile CarrierFile;
    	DWORD BaseFileLen;
    	DWORD CarrierFileLen;
    	
    	unsigned char* BaseData;
    	unsigned char* CarrierData;
    	
    	if(m_bBaseBMPResume==true && m_bBasefile==true)
    	{
    		CarrierFile.Open(m_sCarrierFileResume,CFile::modeReadWrite);
    		CarrierFileLen=CarrierFile.GetLength();
    		BaseFile.Open(m_sBaseFile,CFile::modeReadWrite);
    		BaseFileLen=BaseFile.GetLength();
    
    		if(BaseFileLen!=CarrierFileLen)
    		{
    			AfxMessageBox("选取的不是充作载体的原始文件!");
    			CarrierFile.Close();
    			BaseFile.Close();
    			return;
    		}
    		
    		CarrierData=new unsigned char[CarrierFileLen];
    		CarrierFile.Read(CarrierData,CarrierFileLen);
    
    		BaseData=new unsigned char[CarrierFileLen];
    		BaseFile.Read(BaseData,CarrierFileLen);
    
    		if(CarrierData[28]!=24)
    		{
    			AfxMessageBox("载体文件格式错误!");
    			CarrierFile.Close();
    			BaseFile.Close();
    			if(CarrierData!=NULL)
    				delete CarrierData;
    			if(BaseData!=NULL)
    				delete BaseData;
    			return;
    		}
    		if(BaseData[28]!=24)
    		{
    			AfxMessageBox("原始文件格式错误!");
    			CarrierFile.Close();
    			BaseFile.Close();
    			if(CarrierData!=NULL)
    				delete CarrierData;
    			if(BaseData!=NULL)
    				delete BaseData;
    			return;
    		}
    
    		unsigned char Temp=0;
    		DWORD j=0;
    		for(DWORD i=54;i<CarrierFileLen;i++)
    		{
    			Temp=(ShowCalculate(CarrierData[i],BaseData[i])&7)<<5;
    			i++;
    			Temp|=(ShowCalculate(CarrierData[i],BaseData[i])&7)<<2;
    			i++;
    			Temp|=(ShowCalculate(CarrierData[i],BaseData[i])&6)>>1;
    			CarrierData[j]=Temp;
    			j++;
    			Temp=(ShowCalculate(CarrierData[i],BaseData[i])&1)<<7;
    			i++;
    			Temp|=(ShowCalculate(CarrierData[i],BaseData[i])&7)<<4;
    			i++;
    			Temp|=(ShowCalculate(CarrierData[i],BaseData[i])&7)<<1;
    			i++;
    			Temp|=(ShowCalculate(CarrierData[i],BaseData[i])&4)>>2;
    			CarrierData[j]=Temp;
    			j++;
    			Temp=(ShowCalculate(CarrierData[i],BaseData[i])&3)<<6;
    			i++;
    			Temp|=(ShowCalculate(CarrierData[i],BaseData[i])&7)<<3;
    			i++;
    			Temp|=ShowCalculate(CarrierData[i],BaseData[i])&7;
    			CarrierData[j]=Temp;
    			j++;
    		}
    		BaseFile.Close();
    		CarrierFile.Close();
    		j=0;
    		CString FileName="";
    		while(true)
    		{
    			if(CarrierData[j]=='*')
    			{
    				j++;
    				break;
    			}
    			else
    			{
    				FileName+=CString(CarrierData[j]);
    				j++;
    			}
    		}
    		CString FileLen="";
    		while(true)
    		{
    			if(CarrierData[j]=='*')
    			{
    				j++;
    				break;
    			}
    			else
    			{
    				FileLen+=CString(CarrierData[j]);
    				j++;
    			}
    		}
    		BaseFileLen=atoi(FileLen);
    
    		CFile file;
    		file.Open(FileName,CFile::modeCreate|CFile::modeReadWrite);
    		file.Write(CarrierData+j,BaseFileLen);
    		file.Close();
    		AfxMessageBox("信息恢复完毕!");
    
    		if(BaseData!=NULL)
    			delete BaseData;
    		if(CarrierData!=NULL)
    			delete CarrierData;
    	}	
    }
    


    展开全文
  • 神经网络与信息隐藏的结合

    千次阅读 2020-03-25 09:52:16
    神经网络与信息隐藏的结合 Contents 1 引言... 1 2 切入点介绍... 1 2.1 SGAN & SSGAN.. 1 2.2 使用神经网络生成隐写失真代价... 1 2.3 使用神经网络做隐写分析... 1 2.4 生成含秘载体... 2 3 面临的...

    神经网络与信息隐藏的结合

    Contents

    1 引言... 1

    2 切入点介绍... 1

    2.1 SGAN & SSGAN.. 1

    2.2 使用神经网络生成隐写失真代价... 1

    2.3 使用神经网络做隐写分析... 1

    2.4 生成含秘载体... 2

    3 面临的挑战及机遇... 2

    3.1 和GAN网络进行融合... 2

    3.2使用神经网络生成隐写失真代价... 2

    3.3 使用神经网络做隐写分析... 2

    3.4 使用神经网络实现水印的嵌入... 2

    4 关于设备和最后总结... 3

    参考文献... 4

    1 引言

    以下是我对目前神经网络和信息隐藏的交叉点进行了总结,知识匮乏,该文章只能代表我目前的对该领域的理解程度。从信息隐藏转型到神经网络深度学习的话,我认为有四个点可以进行切入:Semi-Supervised Learning with Generative Adversarial Networks(SGAN);使用神经网络做隐写分析;使用神经网络生成隐写失真代价;使用神经网络直接生成含秘载体。接下来将展开叙述。

    2 切入点介绍

    2.1 SGAN & SSGAN

    SGAN是GAN的一种改进传统的GAN在判别器网络的输出端会使用二分类模式,代表真和假,在SGAN中,就是把这个二分类(sigmoid)转化为多分类(softmax),类型数量为N+1,指代N个标签的数据和“一个假数据”。在GAN网络中,我们会用到很多的对抗样本,通过对某个图像加一个轻微扰动就可以骗过解码器,而对抗样本本质上可以看作一种特殊的隐写,对抗样本让人类看似图片还是原来的样子,但可以成功骗过解码器。所以可以将隐写分析的原理用于训练之中用于区分出假数据。

    2.2 使用神经网络生成隐写失真代价

    使用神经网络生成失真代价,即可实现自适应隐写。在隐写中,我们关注于图像在嵌入秘密信息后和嵌入之前变化的大小,如果变化太大我们将认为这不是一种好的隐写方案。我们可以使用神经网络来调整参数,生成隐写是真代价,选择最好的嵌入位置。

    2.3 使用神经网络做隐写分析

    隐写分析也是信息安全中的一个重要方面,之前我们多用手工来进行隐写分析,现在证明深度学习在图像分辨上具有很好的性能,我们可以把隐写分析的工作交给深度学习来做,和图片分类不同,隐写的图像和原图极其相似,所以其信号会很弱,可能需要选取更优秀的网络,或者进行一些优化改进。

    2.4 生成含秘载体

    直接使用神经网络生成含秘载体,是使用深度学习在图像水印及信息隐藏上的里程碑,李飞飞团队在论文hiding data with deep networks中实现了这一功能。

    3 面临的挑战及机遇

    3.1 和GAN网络进行融合

    对抗生成网络目前很火,对待分类图像加一个轻微的扰动,就可以欺骗神经网络,出现分类错误。通过将隐写分析的一些基础规则应用于GAN网络中,可以帮助GAN网络进行训练。我认为如果从这个点切入需要有深度学习的基础知识,并且最好了解GAN网络,而这类攻防大赛已经很成熟,可以考虑参加各类比赛来激发学习兴趣,难度四星

    3.2使用神经网络生成隐写失真代价

    用神经网络辅助秘密信息的嵌入,可以选择出较好的嵌入位置而降低由于信息隐写引起的失真。从这一点切入需要我们有一些信息隐藏、图像水印的知识,把神经网络当作一种工具来使用,属于较易实现的一个点,难度二星

    3.3 使用神经网络做隐写分析

    目前神经网络用于最多的场景就是图像分类,图像识别,这也是现在神经网络凸显出优势的方面,可以借鉴现有的神经网络进行修改来用于隐写分析,从该方向切入,需要较深的神经网络知识,理解神经网络的网络结构,能够对网络结构做出一定的修改,难度四星

    3.4 使用神经网络实现水印的嵌入

    直接使用深度学习神经网络实现水印的嵌入无疑是一个之前没什么人做过的方向,直接生成载秘图像,李飞飞团队正是在做这方面工作,使用神经网络直接进行载体图像和秘密信息融合的效果目前并不是特别好。这个方向无疑是最难的,需要对神经网络有很深的基础,并且能够自己设计神经网络的架构,虽然有所参考,但需要吃透后再进行修改完善,难度五星

    4 关于设备和最后总结

    至于深度学习所要使用的设备,反而不用太过于担心,目前各种云服务平台很多,价格低廉,以5元/小时的价格就可以租用到一块2080ti的显卡,前期实验阶段,免费的资源甚至自己的笔记本足够使用。相比于设备更加重要是拥有扎实的基础知识和选择一个好的切入点。

     

     

    参考文献

    [1] 2019 福州大学 CSIG中国行

    [2] Zhu, Jiren, et al. "HiDDeN: Hiding Data with Deep Networks." european conference on computer vision (2018): 682-697.

    展开全文
  • 网页信息隐藏及一种方法

    千次阅读 2007-03-02 15:41:00
    信息隐藏技术: 按载体的不同分为图像、视频、声音和文本等数字媒体的信息隐藏技术。 目前的研究集中在以静止图像、音频及视频为载体的数字媒体上,针对文本信息隐藏技术的研究较少。文本载体的信息冗余太少,不...
  • 2014年频繁降价,真正发挥规模优势和资源优势;在前阿里云总裁胡晓明任职的4年时间里,阿里云奠定了在行业中的领军地位。近日,华尔街知名投行高盛发布2018年第三季度云计算行业指出,随着全球云计算市场规模的持续...
  • Linux特点与优势

    千次阅读 2016-03-14 19:33:44
    3. Linux在内存管理优势:Windows是只在需要内存时,才为应用程序分配内存;Linux 无论物理内存有多大,都将其充份利用。 4. Linux可以随意切换桌面环境。 5. 不需要整理磁盘碎片。 微软FAT文件系统:尽可能地将...
  • 数据挖掘一般是指从大量的数据中通过算法搜索隐藏于其中信息的过程。 12. 数据(Data)-信息(information)-知识(Knowledge)是一个递进的关系。 13. 数据挖掘的步骤一般可以分为:数据提取(ETL)-数据仓库-...
  • jQuery中的ajax的优势和不足

    千次阅读 2016-11-09 10:08:54
    并有代替传统的Web方式和通过隐藏的框架来进行异步提交的趋势,是Web开发应用的一个里程碑。 现在就先说说Ajax的优势和不足吧。 优势: 1.不需要插件支持 现在可以被绝大多数主流浏览器支持,当然用户只需要允许...
  • go 语言 优势及 主要用途

    万次阅读 2016-09-05 13:35:53
    1、Go有什么优势 可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了。 静态类型语言,但是有动态语言的感觉,静态类型的语言就是可以在编译的时候检查出来隐藏的大多数...
  • Android开发UI之隐藏系统状态栏

    千次阅读 2015-11-10 15:26:57
    Android开发UI之隐藏系统状态栏前言这一篇我们将涉及一下内容: 1.在4.0及以下版本中隐藏状态栏 2.在4.1及以上版本中隐藏状态栏 3.在4.4及以上版本中隐藏状态栏 4.让内容显示在状态栏之后 5.同步状态栏与Action Bar...
  • 隐藏层的简单理解

    万次阅读 2007-08-05 02:32:00
    在多级前馈网当中,隐藏层的定义是:除输入层和输出层以外的...该层负责接收来自网络外部的信息,被记作第0层. 什么是输出层,它是网络的最后一层,具有该网络的最大层号,负责输出网络的计算结果. 从上面的话可以粗略的看
  • 金字塔池化过程及其优势

    千次阅读 2017-05-23 13:13:29
    金字塔池化过程及其优势  第一次完全自己动手写博文,起初有点不知所措,后来是有种深深的责任感,经过查阅了一些资料,才敢动笔,可能有些地方没有完全领悟到,期望各位同仁予以指正。   虽然在 池化总结...
  • jQuery的用途和优势

    千次阅读 2019-01-25 19:48:18
    利用jQuery可以方便地获取和修改页面中的指定元素,如:添加,删除商品,留言,个人信息等。 二. 控制页面样式 用jQuery可以很便捷地控制页面的CSS文件,用jQuery操作页面的样式可以很好地兼容各种浏览器,比如:...
  • 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能; 与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都...
  • Cypress测试实例凸显其优势
  • Java的成员隐藏与属性封装

    千次阅读 2017-03-21 23:38:34
    如果需要对数据的信息进行修改或者获取,不会直接修改成员信息,而是通过方法的调用来实现。  写如下代码: packagefengzhuang;   class HuaShanPai {  private String zhangmen;  private int
  • 零售机价位也一般,没有什么优势。 A1518移动定制版,移动卡的用户可以购买, 国行的定制版,性价比都很低, 懂的人都会买国行A1530,电信用户也会选择美版V版!!  现在买二手机的人很多,买二手机的时候...
  • Linux进程隐藏的一种实现思路

    千次阅读 2017-01-18 03:02:21
    本文概要:一种 Linux 中进程隐藏的思路、操作与步骤截图 前置知识:最好对 Linux 下编译程序略知一二(文末有知识注解与扩展阅读,最后奉上网易小风景) 感谢 NSRC 老司机团长的分享~  前言 ...
  • Go语言的优势在哪里

    千次阅读 2016-08-04 23:44:01
    Go语言的优势在哪里 部署简单 Go 编译生成的是一个静态可执行文件,除了 glibc 外没有其他外部依赖。这让部署变得异常方便:目标机器上只需要一个基础的系统和必要的管理、监控工具,完全不需要操心应用所需的...
  • 为什么要学 Flink,Flink 优势在哪?

    千次阅读 2019-08-27 07:36:32
    知道大数据的同学也应该知道 Flink 吧,最近在...: Flink的故障恢复机制是通过建立分布式应用服务状态一致性检查点实现的,当有故障产生时,应用服务会重启后,再重新加载上一次成功备份的状态检查点信息。结合可重放的...
  • 信息检索复习笔记

    万次阅读 2020-12-17 17:14:46
    信息检索复习 第一讲 搜索 IR(信息检索是什么样的学科): 实质上是融合了文本及多媒体检索、数据挖掘、机器学习和自然语言处理的综合学科 为什么要进行信息检索?信息过载 搜索 搜索的过程 从大规模非结构化数据...
  • 谷歌弃用形同虚设的图片验证码...短信验证码作为互联网交互中的重要环节,保卫着网站的安全以及我们的信息安全。用户体验差、毫无安全性可言的图片验证码将退出历史舞台,未来将会是安全与体验双重保障的验证码的时代。
  • 【java】类中使用getter和setter的优势

    千次阅读 2018-03-25 10:59:57
    java有三大特性:封装,继承还有多态。而今天,我来讲一下...概念:封装也称为信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内...
  • java技术有哪些优点优势

    万次阅读 2017-04-19 15:52:21
    对象中封装了它的状态变量以及相应的方法,实现了模块化和信息隐藏;而类则提供了一类对象的原型,并且通过继承机制,子类可以使用父类所提供的方法,实现了代码的复用。 3. 分布性 Java是面向网络的语言...
  • Part1. OSGi的优势和可能遇到的问题

    千次阅读 2015-08-23 21:19:37
    模块化并不仅仅是把系统拆分为不同的块而已——这是JAR包就能够做的事情,真正的模块化必须考虑到模块中类的导出、隐藏、依赖、版本管理、生命周期变化和模块间交互等一系列的问题。 2、OSGi可以弥补java中资源精细...
  • 这是因为DNS本身的协议脆弱性导致其很容易被利用,且攻击者可以很好地隐藏自己。DNS隧道攻击就是攻击者经常使用的攻击手段之一,本期云学堂解析DNS隧道攻击的原理,分享判断隧道攻击的基本思路,enjoy: 一、DNS...
  • 在物联网领域,5G无疑是现在热议的话题之一,然而,在2020年以前,5G的大规模应用,...NB-IoT能够得到一定的重视,那么必然有其可取之处,那NB-IoT的优势是什么? 作为一项应用于低速率业务中的技术,NB-IoT的优势...
  • 利用多层卷积神经网络(CNN)特征的互补优势 进行图像检索 本文原网址为:http://www.sciencedirect.com/science/article/pii/S0925231216314734 翻译不当之处请多多指正 摘要:深度卷积神经网络已经证明了图像分类...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,507
精华内容 29,402
关键字:

信息隐藏的优势