|
信息隐藏指在设计和确定模块时,使得一个模块内包含的特定信息(过程或数据),对于不需要这些信息的其他模块来说,是透明的。
传统的信息隐藏起源于古老的隐写术。如在古希腊战争中,为了安全地传送军事情报,奴隶主剃光奴隶 的头发,将情报文在奴隶的头皮上,待头发长起后再派出去传送消息。我国古代也早有以藏头诗、藏尾诗、漏格诗以及绘画等形式,将要表达的意思和“密语”隐藏在诗文或画卷中的特定位置,一般人只注意诗或画的表面意境,而不会去注意或破解隐藏其中的密语。 信息隐藏的发展历史可以一直追溯到"匿形术(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);
- }
复制代码
作者:yincheng01 发表于2011-12-15 7:40:27 原文链接
|
|