LSB隐写(最低有效位隐写)

LSB隐写(最低有效位隐写)

我们先思考如下几个问题,然后再去实现
1、图片在计算机中存储的方式
2、什么原因可以是实现隐写
3、为什么选择最低有效位?
4、具体实现思路
5、如果用代码实现LSB隐写

1、图片在计算机中存储的方式
        如果将一幅图像放大,我们可以看到它是由一个个的小格子组成的,每个小格子就是一个色块。如果我们用不同的数字来表示不同的颜色,图像就可以表示为一个由数字组成的矩阵(matrix),这样就可以在计算机中存储。这个小格子就是像素(pixel),矩阵的行数与列数,就是分辨率(resolution)。
        我们常说某张图像的分辨率是1280*720,指的就是这张图像是由1280行,720列的像素组成。反过来,如果我们有一个矩阵,将矩阵中的每个数值都转换为颜色,并在计算机中显示出来,就可以复现这张图像
在这里插入图片描述
        我们可以理解为图像在计算机中是以点阵的形式存在的,我们可以理解为一个二位数组或者矩阵,每个点所在的行和列是它的坐标,元素的值可以理解为当前像素的值。
2、什么原因可以实现隐写
        这个原因有很多,但是最重要的还是因为人类的视觉冗余,其实是对相近的像素的敏感度比较低。所以改变部分像素的值不是很明显的话,肉眼基本察觉到不到。
3、为什么选择最低有效位?
如果我们使用RGB方式即0—255无符号数字对某个像素点的值进行描述的时候,我们怎么修改这个数字才能实现我们写入数据的功能而且对原图的修改程度最小?我们都知道计算机是基于二进制的,也就是说我们在计算机中能见到的一切数据都是以二进制的形式存在的。例如:
在这里插入图片描述
比如说十进制数据253对应的二进制数据是1111 1101‬,即使是字符串也是可以转换为二进制类型的数据,我们只需要把要隐藏的数据先转换为二进制数据然后再将其按照某种规则差分然后按位写入图像的部分像素的二进制数据的最后一位即可。
如果图片中某点的像素值是253的话,其对应的二进制数据是1111 1101,如果我们把该数据的最后一位替换为0的话,其对应的十进制数据就是252。
在这里插入图片描述
因为人眼的视觉冗余,对图片中某点的像素发生上述改变时几乎是察觉不到的。因为图像隐写的目的是不让别人发现写入了数据,先不说写入的问题,如果说图像本身的变化人眼就能识别的话,何谈“隐”字?这种方式对图像的改变比较小,所以采用该方式。
4、具体实现思路
(1)获取要隐藏的数据,一般这里不管是什么,我们都可以理解为字符串,本文不涉及图像写入图像。
(2)将获取到的字符串二值化,即按照一定规则转换为二进制数据,一般是8位(不涉及中文隐写,中文占2个,因为我实验的目的虽然是实现隐写,我还想提出来呢,并不是写进去不提出来,所以我得有规则),不够的前面补0,一定要测试好对应的解码方法。
(3)准备好宿主图像,安装好python环境和PIL,我们不使用opencv实现,因为opencv可能存在着压缩,我没有实现,最后使用PIL实现的。
(4)获取图像信息(主要是高度和宽度),这里作为入门,我们不使用彩色图像,以黑白图像为例,根据二值化后的字符串的长度,对宿主图像的像素进行遍历,然后将数据依次写入对应像素的最低有效位,写入完成之后跳出循环,对目标图像进行持久化即可得到载密图像。
5、实现

	from PIL import  Image as im
	import re
	
	replace_reg = re.compile(r'[1|0]$')
	
	#替换最后一位的数据,source是被替换数据,target是目标数据,就是batarget放到source最后一位
	def repLstBit(source,target):
	    return replace_reg.sub(target,source)
	#运行结果:'123X'
	print(repLstBit("111110","1"))
	
	#字符串转换二进制,不够八位的话补齐8位
	def encode(s):
	    return ''.join(bin(ord(c)).replace('0b','').rjust(8,'0') for c in s)
	
	#切割从图像中收集到的数据,就是把载密图像的对应最后一位提取出来之后需要进行切割
	def cut_text(text,lenth):
	    textArr = re.findall('.{'+str(lenth)+'}',text)
	    tempStr = text[(len(textArr) * lenth):]
	    if len(tempStr)!=0:
	        textArr.append(text[(len(textArr)*lenth):])
	    return textArr
	
	#二进制转换成字符串,看上面切割方法的注释即可理解该方法存在的意义
	def decode(s):
	    bitArr = cut_text(s,8)
	    return "".join(chr(int(i,2)) for i in bitArr)
	
	
	#读取宿主图像和要写入的信息生成载密图像。
	if __name__ == '__main__':
	    img = im.open("D:/StegAnograpy/dove.png")
	    width = img.size[0]
	    height = img.size[1]
	    hideInfo = "Hello ImageSteg"
	    hideBitArr = encode(hideInfo)
	    count = 0
	    bitInfoLen = len(hideBitArr)
	
	    print(hideBitArr)
	    for i in range(width):
	        for j in range(height):
	            if count == bitInfoLen:
	                break;
	            pixel = img.getpixel((i,j));
	            print(pixel[0])
	            sourceBit = bin(pixel[0])[2:]
	            print(sourceBit)
	            rspBit = int(repLstBit(sourceBit,hideBitArr[count]),2)
	            count += 1
	            img.putpixel((i,j),(rspBit,rspBit,rspBit))
	    img.save("D:/StegAnograpy/dove1.png")


6、StegSolve检测结果:
在这里插入图片描述
7、总结
(1)这种方式比较容易实现,但是太容易被检测到。
(2)但是本次实验的收获是直到了从0到1的细节处理。

没有积分的私聊我 看到消息百分百发给你 1、算法核心: 1、读取图片A,获得其RGB三个通道数据并转换成三个矩阵a1,a2,a3。 2、读取文件B,将其转换成比特流b。 3、遍历b,得到比特b1,b2,b3,b4,b5,b6等等,将b1代替a1第一个元素的最低位,将b2代替a2第一个元素的最低位,将b3代替a3第一个元素的最低位,将b4代替a1第二个元素的最低位,以此类推。 2、具体实现: 1、: 1、使用java ImageIO读取图片,获取其RGB通道信息。 2、使用java NIO读取被嵌入的文件,将其转换为byte数组,需要特别指出的是原生方法得到是byte类型的数组,但是算法实现需要更加精细的操作,所以还需要对得到的byte数组进行进一步的转换封装,将其转换成形如10101的数组。例如,读取文件得到byte数组的第一个元素为63,需将63转换为00111111数组。并且保存好文件的长度。 3、按照算法,遍历形如10101的数组 1、如果遍历到的值为0,将矩阵对应的矩阵元素与0xfe进行与运算,将最低位置为0 2、如果遍历到的值为1,将矩阵对应的矩阵元素与0x01进行或运算,将最低位置为1 4、将步骤3得到的经过经过的矩阵为一张新的图片。 3、读取 1、使用java ImageIO读取图片,获取其RGB通道信息。 2、使用步骤3得到的文件长度,遍历图片的像素矩阵,需要特别指出的是因为后续步骤还需要进行进一步的转化,所以这一步是将得到的“100100......”序列每八位封装为一个数组,最终得到一些数组集合,每个数组包含八位二进制序列。 3、将步骤2得到的数组进行转换,例如00111111应该转换为byte类型数值为63的数字,10111111转换为-63。这一步会得到一个byte类型的数组。 4、将步骤3得到的byte类型数组入文件,需要指出的是入的文件形式应该和模块步骤二中读入的文件形式一致。 3、程序使用方法 1、安装Java8 2、使用命令行进入jar文件所在目录下,使用命令 java -jar 2016115130.jar 3、安装提示输入嵌入和被嵌入的文件名字,注意路径问题
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值