文章目录
任务
编程实验,实现基于LSB算法的,在图片中进行信息隐藏的程序,并用自己的姓名或者学号作为要隐藏的信息。
1.首先明确操作的原理
原理
LSB全称为 least significant bit,是最低有效位的意思。Lsb图片隐写是基于lsb算法的一种图片隐写术,这是一种常见的信息隐藏方法。LSB算法是将信息的每一位隐藏到图片RGB单元的最后一位,由于一位的改变对于颜色影响不大,人的肉眼难以识别,从而达到信息隐藏的效果。
相关信息的补充
首先来讲png图片,png图片是一种无损压缩的位图片形格式,也只有在无损压缩或者无压缩的图片(BMP)上实现lsb隐写。如果图像是jpg图片的话,就没法使用lsb隐写了,原因是jpg图片对像数进行了有损压缩,我们修改的信息就可能会在压缩的过程中被破坏。而png图片虽然也有压缩,但却是无损压缩,这样我们修改的信息也就能得到正确的表达,不至于丢失。BMP的图片也是一样的,是没有经过压缩的。BMP图片一般是特别的大的,因为BMP把所有的像数都按原样储存,没有进行压缩。
png图片中的图像像数一般是由RGB三原色(红绿蓝)组成,每一种颜色占用8位,取值范围为0x00~0xFF,即有256种颜色,一共包含了256的3次方的颜色,即16777216种颜色。而人类的眼睛可以区分约1000万种不同的颜色,这就意味着人类的眼睛无法区分余下的颜色大约有6777216种。所以用LSB算法可以达到信息隐藏的效果。
2.进行操作的思如如下
2.1隐藏信息
①首先准备好要读取的图片,和要加密的数据。
②然后将要加密的数据化转化为2进制字符串。
③然后,读取图片数据为3维数组,找到n个点,(n等于要加密2进制字符串的长度)。
④将③中的图片上的点,按顺序,对每个点所存储的数据,转化为2进制,然后将最后一位bit 位的数据,按顺序替换为要加密的2进制字符。
⑤将替换后的图像的3维数组数据保存输出为图像,即为隐藏了加密信息的图片。
2.2读取隐藏信息
①读取加密后的图片的信息为3维数组。
②找到依次加密的点的数据,将最后一位bit位上的数合并起来得到加密的二进制字符串。
③将加密的二进制字符串转还原为解密后的数据。
3.遇到的问题
①cv2库的imread读取路径不能包含中文。
②隐藏中文和数字的方式不同,所以设置了2种方式,实现分别对中文和数字的隐藏。
补充的python函数内容
主要是字符串、数字、中文间的转化:
可以参考的文章:
python(中文、数字(2进制、10进制、16进制)、字符串)之间的转换
4.具体的操作代码的如下
用到的工具:python。
4.1读取图片数据
import random
import cv2
import copy
#读取一副图片
image=cv2.imread(r'C:\Users\yunmeng\Desktop\1.png')
#修改前的图像
pre_image=copy.deepcopy(image)
#待修改的图像的数据
after_image=copy.deepcopy(image)
读取后的图片的信息为3维的数组据矩阵如下:
4.2隐藏(数字数据),各函数的设计
①隐藏数据函数
def disguise(pre_image,disguise_information):
#获取读到图片的信息
mysize=after_image.shape
#需隐藏的图片的信息
message=bin(disguise_information).replace('0b','')
l=len(message)
#这里采用集合对点的数据进行存储,为了不让点出现重复
m_n_list=set([])
#要替换的位置坐标(m,n)
def generate_random(count):
if(len(m_n_list)<count):
m=random.randrange(0,mysize[0],1)
n=random.randrange(0,mysize[1],1)
tem=(m,n)
m_n_list.add(tem)
generate_random(count)
random.seed(1)
generate_random(l)
m_n_list=list(m_n_list)
#进行数据的替换
for i in range(l):
replace_num = after_image[m_n_list[i][0], m_n_list[i][1], 1]
tem_str = bin(replace_num)[:-1] + message[i]
tem_num=int(tem_str.replace('0b', ''), 2)
after_image[m_n_list[i][0], m_n_list[i][1], 1]=tem_num
#保存图片
cv2.imwrite(r'C:\Users\yunmeng\Desktop\2.png',after_image)
#将加密所在的位置m,n,数据进行存储。
with open(r'D:\Users\yunmeng\PycharmProjects\数据分析\课程作业相关代码文件\lsb算法加密\m_n','w') as f:
f.write(str(m_n_list))
return m_n_list
②进行数据的隐藏,同时保存图片中隐藏的点的位置的数据。
m_n=disguise(pre_image,20210010001)
③定义读取隐藏信息的函数
def gain_password(after_image,m_n_list):
#读取加密的图片文件
#after_image=cv2.imread(path)
password=[]
for j in range(len(m_n_list)):
m=m_n_list[j][0]
n=m_n_list[j][1]
tem_num=after_image[m,n,1]
tem_str = bin(tem_num)[-1]
password.append(tem_str)
password=''.join(password)
password=int(password,2)
return password
④读取隐藏信息
gain_Password=gain_password(after_image,m_n)
print('gain_Password:',gain_Password)
结果如下图:
4.4.加密前后的图像的对比
左前,右后。
可以看出加密前后,除了像素点不同外,几乎看不出其他的任何变化。
4.3隐藏(中文数据),函数的设计
①隐藏数据函数
def disguise(pre_image,disguise_information,):
#获取读到图片的信息
mysize=after_image.shape
#需隐藏的图片的信息
whole_word = ''
word_sep = []
tem_sep = 0
for i in disguise_information:
single_word = format(ord(i), 'b')
whole_word += single_word
l = len(single_word)
tem_sep += l
word_sep.append(tem_sep)
message=whole_word
l=len(message)
m_n_list=set([])
#要替换的位置坐标(m,n)
def generate_random(count):
if(len(m_n_list)<count):
m=random.randrange(0,mysize[0],1)
n=random.randrange(0,mysize[1],1)
tem=(m,n)
m_n_list.add(tem)
generate_random(count)
random.seed(1)
generate_random(l)
m_n_list=list(m_n_list)
#进行数据的替换
for i in range(l):
replace_num = after_image[m_n_list[i][0], m_n_list[i][1], 1]
tem_str = bin(replace_num)[:-1] + message[i]
tem_num=int(tem_str.replace('0b', ''), 2)
after_image[m_n_list[i][0], m_n_list[i][1], 1]=tem_num
#保存图片
cv2.imwrite(r'C:\Users\yunmeng\Desktop\2.png',after_image)
#将加密所在的位置m,n,数据进行存储。
with open(r'D:\Users\yunmeng\PycharmProjects\数据分析\课程作业相关代码文件\lsb算法加密\m_n','w') as f:
f.write(str(m_n_list))
f.write('\n')
f.write(str(word_sep))
return m_n_list,word_sep
②进行数据的隐藏,同时保存图片中隐藏的点的位置的数据。
m_n,sep=disguise(pre_image,'云梦之上')
③定义读取隐藏信息的函数
def gain_password(after_image,m_n_list,sep):
#读取加密的图片文件
#after_image=cv2.imread(path)
password=[]
for j in range(len(m_n_list)):
m=m_n_list[j][0]
n=m_n_list[j][1]
tem_num=after_image[m,n,1]
tem_str = bin(tem_num)[-1]
password.append(tem_str)
password=''.join(password)
chinese_words=[]
for i in range(len(sep)):
if i==0:
tem_word = password[0:sep[i]]
else:
tem_word=password[sep[i-1]:sep[i]]
word=chr(int(tem_word,2))
chinese_words.append(word)
return chinese_words
④读取隐藏信息
gain_Password=''.join(gain_password(after_image,m_n,sep))
print('gain_Password:',gain_Password)