隱寫術(shù)-LSB算法

實(shí)驗(yàn)要求:
利用LSB算法將自己姓名隱藏到一張彩色圖片
(R通道)中。
可以從圖片中提取出隱藏的信息

實(shí)驗(yàn)用的是bmp文件。
bmp文件頭(bmp file header):提供文件的格式、大小等信息
位圖信息頭(bitmap information):提供圖像數(shù)據(jù)的尺寸、位平面數(shù)、壓縮方式、顏色索引等信息
調(diào)色板(color palette):可選,如使用索引來表示圖像,調(diào)色板就是索引與其對(duì)應(yīng)的顏色的映射表
位圖數(shù)據(jù)(bitmap data):就是圖像數(shù)據(jù)啦_

推薦一個(gè)軟件(010 Editor),可以清楚的看到文件的二進(jìn)制格式


軟件介紹

bmp文件頭

可以看到偏移量為54個(gè)字節(jié)


每個(gè)像素的信息

所以可以用c++打開這個(gè)二進(jìn)制文件,然后將字符串轉(zhuǎn)化為二進(jìn)制,最后添加到R通道的最后一位。

思路簡單,但是代碼稍微復(fù)雜一點(diǎn)
代碼如下:
頭文件:

#pragma once
#include <windows.h>
#define  _CRT_SECURE_NO_WARNINGS
using namespace std;
class HideBmp
{
public:
    HideBmp(char* hstr);
    ~HideBmp();
    bool GetBmp(char* bmp);
    bool hidestring();
    bool showstring();
    int strtobin(char* hidestr);

private:
    BITMAPFILEHEADER *bmfh;//bmp文件信息
    char* hidestr;//需要隱藏的字符串
    LPBYTE pBuf;    //存儲(chǔ)bmp文件
    DWORD BmpSize;  //bmp文件的大小
    BYTE* bin_str;  //字符串的二進(jìn)制形式
    int strsize;    //字符串的長度


};

zjx_lsb.cpp

#include "zjx_lsb.h"
#include <fstream>
#include <iostream>
#include <typeinfo>
#include <sstream>
HideBmp::HideBmp(char* hstr)
{
    this->hidestr = hstr;
    this->pBuf = 0;
    this->BmpSize = 0;
    this->bin_str = new BYTE[8*strlen(hidestr)];
    this->strsize=strlen(hidestr);
}
HideBmp::~HideBmp()
{

}
//將字符串轉(zhuǎn)化為二進(jìn)制
int HideBmp::strtobin(char* hidestr)
{
    char temp_str;
    int count = 0;
    char* temp_bin_str = new char[8];
    for (int i = 0; i < strlen(hidestr); i++)
    {
        temp_str = hidestr[i];
        for (int j = 0; j < 8; j++)
        {
            if (temp_str % 2 == 0)
            {
                temp_bin_str[j] = '0';
            }
            else
            {
                temp_bin_str[j] = '1';
            }
            temp_str /= 2;
        }
        for (int k = 0; k < 8; k++)
        {
            bin_str[count] = temp_bin_str[7 - k];
            count++;
        }


    }

    return 0;
}
/*將圖片的信息全部讀入pBuf中*/
bool HideBmp::GetBmp(char*  bmp)
{
    if (pBuf)
    {
        delete[] pBuf;
    }
    HANDLE hfile = CreateFileA(bmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
    if (hfile == INVALID_HANDLE_VALUE)
    {
        return false;
    }
    BmpSize = GetFileSize(hfile,0);
    ifstream inFile(bmp, ios::in | ios::binary);
    if (!inFile.is_open()) {
        cout << "open error" << endl;
        return 0;
    }
    pBuf = new byte[BmpSize];
    inFile.read((char*)pBuf,BmpSize);
    cout << "讀入圖片成功" << endl;
    inFile.close();
    bmfh = (BITMAPFILEHEADER*)pBuf;
    return TRUE;
}

bool HideBmp::hidestring()
{
    strtobin(hidestr);
    string FileName = "EncodeBmp.bmp";
    LPBYTE rgbbegin = pBuf + bmfh->bfOffBits + 2;
    
    for (int i = 0, count = 0; count < 8*strsize; count++, i += 3)
    {
        bin_str[count] = (bin_str[count] | 0xFE) & 0x1;
        rgbbegin[i] = (rgbbegin[i] &0xFE)| bin_str[count];
    }
    
    cout << endl;
    cout << "***********************" << endl;
    cout << endl;
    
    ofstream outfile(FileName,ios::out|ios::binary);
    outfile.write((char*)pBuf, BmpSize);
    outfile.close();
    cout << "加密文件生成成功" << endl;
    cout << endl;
    cout << "***********************" << endl;
    return TRUE;
}
bool HideBmp::showstring()
{
    string FileName = "EncodeBmp.bmp";
    char* DeStr=new char[8*strsize];
    ifstream infile(FileName, ios::in | ios::binary);
    LPBYTE de_pBuf=new BYTE[BmpSize];
    infile.read((char*)de_pBuf, BmpSize);
    LPBYTE rgbbegin = de_pBuf + bmfh->bfOffBits + 2;
    for (int i = 0, count = 0; count < 8 * strsize; count++, i += 3)
    {
        if (rgbbegin[i] % 2 == 0)
            DeStr[count] = '0';
        else
            DeStr[count] = '1';
    }
    stringstream ss;
    int a;

    char* str = new char[8];
    char t = 0x1;
    //將解密出的二進(jìn)制賦值
    for (int i = 0; i < strsize; i++)
    {
        str[i] = 0x00;
        
        for (int j = 0; j < 8; j++)
        {
            if (DeStr[i * 8 + j] == '1')
                str[i] = str[i] | (t << (7 - j));
        }
    }
    //輸出解密出的字符串
    cout << endl;
    cout << "***********************" << endl;
    cout << "解密出的字符串:" << endl;
    cout << endl;
    for (int i = 0; i < strsize; i++)
    {
        cout << str[i];
    }
    cout << endl;
    cout << endl;
    cout << "***********************" << endl;
    return true;

}

main.cpp

#include"zjx_lsb.h"
#include <iostream>
int main()
{
    cout << "請(qǐng)輸入要隱藏的字符串" << endl;
    //默認(rèn)200個(gè)字符串
    char* hstr=new char[200] ;
    cin >> hstr;
    HideBmp hmp(hstr);
    hmp.GetBmp("test.bmp");
    hmp.hidestring();
    hmp.showstring();
}

運(yùn)行截圖如下:

image.png

可以看到這兩個(gè)圖片有細(xì)微的差距


原圖.png
加密后的文件格式.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容