基於NODE.JS的LSB寫隱技術在BMP文件的實現

BMP文件中每個像素使用RGB來表示, LSB(Least Significant Bit)最低有效位對應每個顏色的最低位。顏色的範圍是0-255,人眼分辨不出+1/-1的變化。

相關知識點:

1. BMP文件格式

1. node.js文件;

2.node.js的Buffer;

直接上代碼!

爲BMP文件添加信息的函數:

/**
 * fileInput:需要寫入信息的BMP文件;
 * fileOutput:寫好信息後的BMP文件;
 * content:需要寫入的信息;
 */
exports.addWaterMark = function ( fileInput,fileOutput,content ){
    //先檢查下是否是個文件
    fs.stat( fileInput,function(err,stats) {
        if (err) {
            console.log(err.toString());
            return;
        } else {
            if ( !stats.isFile() ) {
                console.log( fileInput + ' is not a file!');
                return;
            }
        }
    });

    //沒有信息的話就直接回去了
    if( content.length==0 )
        return;

    //讀文件並且向裏面添加內容,addMark函數在後面
    fs.readFile( fileInput,function (err,data){
        if( err )
        {
            console.log(err.toString());
            return;
        }
        addMark(data,content,fileOutput);
    } );
};

 

//添加信息的函數
//data--文件內容,這個就是fs.readFile那個回調函數的data
//content--文件內容;
//fileOutput-輸出文件
function addMark(data,content,fileOutput){
    //檢查文件標誌‘BM’--BMP文件標誌
    if( data[0]!=0x42 | data[1]!=0x4D )
        return;

    let i,j,ch1,ch2,index,bitLength;
    let startIndex = 54;//BMP文件的圖像數據是從第54Byte開始的

    //添加標誌信息(010101),有這個的話表示這個文件已經被寫入過信息了
    data[startIndex]   = data[startIndex]   & 0b1110;
    data[startIndex+1] = data[startIndex+1] | 0b0001;
    data[startIndex+2] = data[startIndex+2] & 0b1110;
    data[startIndex+3] = data[startIndex+3] | 0b0001;
    data[startIndex+4] = data[startIndex+4] & 0b1110;
    data[startIndex+5] = data[startIndex+5] | 0b0001;

    //使用Buffer
    let buf = Buffer.from( content,'utf-8' );

    //計算並存儲內容長度信息--32位
    index = startIndex + 6;
    bitLength = 8*buf.length;
    for( i=0;i<32;i++ )
    {
        data[index] = data[index] & 0b1110;
        data[index] = data[index] | ( (bitLength>>i) & 0x0001 );
        index++;
    }

    //添加內容
    index = startIndex + 38;
    for( i=0;i<buf.length;i++ )
    {
        ch1 = buf[i];
        for( j=0;j<8;j++ )
        {
            ch2 = data[index];
            ch2 = ( ch2 & 0b1110 );//set last bit to 0
            data[index] = ( ch2 + ((ch1>>j) & 0x01) );
            index++;
        }
    }

    if( fs.existsSync(fileOutput) )
        fs.unlinkSync( fileOutput );

    //寫入BMP文件
    fs.writeFile( fileOutput,data,function (err){
        if( err )
            console.log(err);
    });
};

 

 

從BMP獲取寫入的內容:

//fileInput:BMP文件

exports.getWaterMark = function ( fileInput ) {
    let content;
    //check file is a file
    fs.stat( fileInput,function(err,stats) {
        if (err) {
            console.log(err.toString());
            return;
        } else {
            if ( !stats.isFile() ) {
                console.log( fileInput + ' is not a file!');
                return;
            }
        }
    });

    //調用getMark函數,並得到寫入的內容,getMark函數在下面
    return getMark( fs.readFileSync(fileInput) );
};

 

//data--文件內容, fs.readFileSync(fileInput)讀出來的文件數據

function getMark(data){
    if( data[0]!=0x42 | data[1]!=0x4D )
        return;

    let i,j,index,bitLength,byteLength;
    let content;

    //檢查是否被標記過(010101)
    let startIndex = 54;
    if( ( (data[startIndex]   & 0x01)==0 ) &&
        ( (data[startIndex+1] & 0x01)==1 ) &&
        ( (data[startIndex+2] & 0x01)==0 ) &&
        ( (data[startIndex+3] & 0x01)==1 ) &&
        ( (data[startIndex+4] & 0x01)==0 ) &&
        ( (data[startIndex+5] & 0x01)==1 )  )
    {
        //獲取內容的長度
        index = startIndex + 6;
        bitLength = 0;
        for( i=0;i<32;i++ )
        {
            bitLength = bitLength | (((data[index] & 0b0001))<<i);
            index++;
        }

        //獲取內容
        byteLength = bitLength/8;
        index = startIndex + 38;
        let buf = Buffer.alloc( byteLength );
        for( i=0;i<byteLength;i++ )
        {
            for( j=0;j<8;j++ )
            {
                buf[i] = buf[i] | (( data[index] & 0x01 )<<j );
                index++;
            }
        }
        content = buf.toString('utf-8');
    }

    return content;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章