文法类隐写与分析技术的实现

文法类隐写与分析技术的实现
1、完成位图格式图像的头文件冗余的数据隐写、分析和提取。

2、完成文件尾部追加的数据隐写、分析和提取。

3、完成BMP位图格式图像的数据区进行数据直接覆盖方式的隐写和分析。

作业用BMP图片,语言为Python,如果有下载完全部需要的库会报错,报错时请仔细查看各个路径修改的是否正确,请正确编写自己的路径或者删除注释#,注释只为更好理解。

# ### 文法类隐写与分析技术的实现
# 
# * 1、完成位图格式图像的头文件冗余的数据隐写、分析和提取。
# 
# * 2、完成文件尾部追加的数据隐写、分析和提取: 
#    
# 
# * 3、完成BMP位图格式图像的数据区进行数据直接覆盖方式的隐写和分析。
#

# In[2]:


#导入所需要的库
import os, sys
import struct
import shutil
from PIL import Image


# In[2]:


#设定图片以及隐藏信息的路径(路径自己设定越简单和短越好,推荐路径尽可能为英文路径,减少汉字路径的使用,orignal_path表示原图的路径,其余的copy_path是各种隐写后的图片路径,max和min表示隐写的文件,一个隐写内容多,一个隐写内容少,但是全是英文字母,切记不要是中文)
orignal_path ="D:/作业用图/12_1.bmp"
copy_path1 = "D:/隐写后图片/steg_12_1_head.bmp"
copy_path2 = "D:/隐写后图片/steg_12_1_eof.bmp"
copy_path3 = "D:/隐写后图片/steg_12_1_data.bmp"
fsize = os.path.getsize(orignal_path)
fmax = open('D:/隐写信息/max.txt', 'r')
datamax = fmax.read()
fmin = open('D:/隐写信息/min.txt', 'r')
datamin = fmin.read()


# In[4]:


# 读取BMP文件数据判断
#Bmp位图文件是基于16进制的,我们需要以16进制的方式去读取文件,
#在python中有一个官方模块struct,里面内置了pack和unpack两个函数,我们可以使用这两个函数对16进制的信息进行打包和解包
def bmp_info(f):
    unpackbuf = struct.unpack('<ccIIIIIIHH', f)  # unpack函数对于16进制信息进行解包
    #’ccIIIIIIHH‘---→格式符 当打包或者解包的时,需要按照特定的方式来打包或者解包.该方式就是格式化字符串
    if (unpackbuf[0] != b'B' or unpackbuf[1] != b'M'):  # 前两个字节是“BM”,用于识别BMP文件的标志
        return None
    else:
        return {
            'bfSize': unpackbuf[2],#4字节整数:表示位图大小
            'bfRserverd': unpackbuf[3],#4字节整数:保留位,始终为0
            'bfOffBits': unpackbuf[4],#4字节整数:实际图像的偏移量
            'biSize': unpackbuf[5],#4字节整数:Header所需的字节数
            'biWidth': unpackbuf[6],#4字节整数:图像宽度
            'biHeight': unpackbuf[7], #4字节整数:图像高度
            'biPlames':unpackbuf[8],# #一个2字节整数:颜色平面数,始终为1
            'biBitCount': unpackbuf[9]#一个2字节整数:比特数/像素。
        }





# 头文件冗余隐写:修改文件头中的保留字段隐藏信息
def header_stegano():
    shutil.copy(orignal_path, copy_path1)#复制文件从src到dst。
    with open(copy_path1, 'r+b') as sfr: #已读写二进制模式打开文件
        str = input('请输入需要隐写的信息:  ')
        sfr.seek(0x0006)#用于移动文件读取指针到指定位置。地址偏移,即保留位的四字节
        sfr.write(str.encode())# 以 encoding 指定的编码格式编码字符串
        sfr.close()
        print("信息隐写成功,请查看隐写后图片的文件夹")
    Operation()


# In[6]:


# 头文件分析
def header_analysis():
    with open(copy_path1, 'rb') as afr:
        afr.seek(0x0006)
        ReserverData = afr.read(4)#读取4字节的数据
        if (ReserverData != 0x0000):
            print("信息隐写成功")
            print("头文件隐写的信息是: ",ReserverData.decode())
        f = open('D:/隐写信息/hidden_header.txt', mode='w')  # 打开文件,若文件不存在系统自动创建。
        f.write(ReserverData.decode())#以 encoding 指定的编码格式解码字符串
        f.close()
    Operation()


# In[7]:


#尾部追加隐写
def eof_stegano():
    shutil.copy(orignal_path, copy_path2)
    with open(copy_path2, 'r+b') as sfr:
        sfr.seek(0, 2)
        print("1.数据量较大(>25%) 2.数据量较小(<1%) ")
        flag = eval(input("请选择: "))#执行选择的命令,并返回表达式的值
        print("")
        if flag == 1:
            sfr.write(datamax.encode())#写入 max的文件内容
            sfr.close()
            print("隐写成功,请查看隐写后图片的文件夹")
            Operation()
        elif flag == 2:
            sfr.write(datamin.encode())#写入 min 文件内容
            sfr.close()
            print("隐写成功,请查看隐写后图片的文件夹")
            Operation()
        else:
            print("Error! Please input again: ")
            Steganography()


# In[8]:


#尾部分析
def eof_analysis():
    with open(copy_path2, 'rb') as afr:
        im = Image.open(copy_path2)  # 返回一个Image对象
        print("------------------------------")
        print('bfwidth:%d, bfheight:%d ' % (im.size[0], im.size[1]))
        size = len(afr.read())
        print("图片实际大小为 {} byte".format(size))
        print("------------------------------")
        flag = eval(input("please input 位深度:"))#24位位图 和 8位位图选项
        # 24位图,一个像素点占3个字节 14位文件头,40位信息头,无调色板
        if flag == 24:
            orignalBytesphoto = im.size[0] * im.size[1] * 3 + 14 + 40
        # 8位位图,一个像素点占1个字节 14位文件头,40位信息头,有颜色表,每个颜色表结构体是4字节,无调色板
        elif flag == 8:
            orignalBytesphoto = im.size[0] * im.size[1] + 14 + 40 + 256 * 4
        else:
            print("Error! Please input again: ")
        afr.seek(fsize)
        ReserverData = afr.read(size - orignalBytesphoto)#保留信息,通过判断源文件和隐写后的图片大小对比
        if (ReserverData != 0x0000):#差不为0 则隐写过
            print("信息隐写成功")  # 判断是否被隐写
            print("The data hidden in the end file is in message 文件夹")
            f = open('D:/隐写信息/hidden_end.txt', mode='w')  # 打开文件,若文件不存在系统自动创建。
            f.write(ReserverData.decode())
            f.close()
        else:
            print("该图片没有被隐写!")
        Operation()


# In[9]:

#数据区的直接覆盖隐写
def bmp_data():
    shutil.copy(orignal_path, copy_path3) #文件复制
    with open(copy_path3, 'r+b') as sfr:
        sfr.seek(0x0054)     #到指定的位置
        print("1.数据量较大(>25%) 2.数据量较小(<1%) ")
        flag = eval(input("请选择: "))
        print("")
        if flag == 1:
            sfr.write(datamax.encode())#写入 datamax内容
            sfr.close()
            print("隐写成功,请查看隐写后图片的文件夹")
            Operation()
        elif flag == 2:
            sfr.write(datamin.encode()) #写入 datamin内容
            sfr.close()
            print("隐写成功,请查看隐写后图片的文件夹")
            Operation()
        else:
            print("Error! Please input again: ")
            Steganography()


# In[1]:

#数据分析  指针移动到偏移位置读取字节的信息长度
def bmp_data_analysis():
    with open(copy_path3, 'rb') as afr:
        afr.seek(0x0054)    #移动到指定位置
        ReserverData = afr.read(len(datamax))  #max文件内容
        if (ReserverData != 0x0000):
            print("信息隐写成功")
            print("The data hidden in te bmp_data file is in message 文件夹")
            f = open('D:/隐写信息/hidden_data.txt', mode='w')  # 打开文件,若文件不存在系统自动创建。
            f.write(ReserverData.decode())  #写入内容到 hidden_data 文件中
            f.close()
            Operation()


# In[11]:


def Steganography():
    print("*********************************")
    print("1.头文件冗余部分的隐写")
    print("2.文件尾部追加隐写")
    print("3.数据区直接覆盖的隐写")
    print("4.退出")
    print("*********************************")
    flag = eval(input("Please input your choice: "))
    print("")
    if flag == 1:
        header_stegano()
    elif flag == 2:
        eof_stegano()
    elif flag == 3:
        bmp_data()
    elif flag == 4:
        Operation()
    else:
        print("Error! Please input again: ")
        Steganography()


# In[12]:


def Analysis():
    print("*********************************")
    print("1.头文件冗余部分的分析")
    print("2.文件尾部追加分析")
    print("3.数据区直接覆盖的分析")
    print("4.退出")
    print("*********************************")
    flag = eval(input("Please input your choice: "))
    print("")
    if flag == 1:
        header_analysis()
    elif flag == 2:
        eof_analysis()
    elif flag == 3:
        bmp_data_analysis()
    elif flag == 4:
        Operation()
    else:
        print("Error! Please input again: ")
        Analysis()


#[13]:


def Operation():
    print("*********************************")
    print("1.隐写")
    print("2.分析")
    print("3.退出")
    print("*********************************")
    flag = eval(input("Please input your choice: "))
    print("")
    if flag == 1:
        Steganography()
    elif flag == 2:
        Analysis()
    elif flag == 3:
        sys.exit()
    else:
        print("Error! Please input again: ")
        Operation()





if __name__ == '__main__':
    Operation()

头文件数据隐写的测试
运行代码,在交互界面选择头文件冗余部分的隐写,输入我们想隐写的消息,这里输入1234来进行测试。

可以看到信息隐写成功,可以在文件夹中查看隐写后的图片。通过工具notepad++的HEX-Editor插件查看隐写后的图片

我们观察不到图像与原图像的区别,证明隐写成功,我们再使用分析,来对其进一步判断调用分析函数。读出隐写信息


文件尾部追加的隐写测试
运行代码,在交互界面选择尾部追加的方式进行隐写,选择隐写数量较大或者较小的进行测试。

通过工具notepad++的HEX-Editor插件查看隐写后的图片信息肉眼直接观察不到图像与原图像的区别,证明隐写初步成功,

调用分析函数。

隐写后的图片分析
该内容同样以文件形式保存进文件夹中

数据区直接覆盖隐写的测试
运行代码,在交互界面选择直接覆盖的方式进行隐写,同样选择隐写数量较大或较小的进行测试

看到信息隐写成功,可以在文件夹中查看隐写后的图片。通过工具notepad++的HEX-Editor插件查看隐写后的图片信息

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年11月7日
下一篇 2023年11月7日

相关推荐