Python 在数字列表中隐藏二进制值
我试图在数字列表中隐藏二进制值(颜色值,这样它们可以稍微改变并保留相同的含义),但我觉得这个方法有点不雅观。具体来说,我对数字列表的更改超出了我的想象,因为我决定将Python 在数字列表中隐藏二进制值,python,steganography,Python,Steganography,我试图在数字列表中隐藏二进制值(颜色值,这样它们可以稍微改变并保留相同的含义),但我觉得这个方法有点不雅观。具体来说,我对数字列表的更改超出了我的想象,因为我决定将NULL字符(00000000)与无信息区分开来。因此,如果二进制字符串为0,我将列表中的数字改为1。如果它有一个1,我将它改为2 这是可行的,但我想问,是否有人能想出一种仍然符合这一标准的改进方法。这就是看似显而易见的xor解决方案失败的条件。以下是我所做工作的简化版本: def encode(pic_data, file_data
NULL
字符(00000000
)与无信息区分开来。因此,如果二进制字符串为0,我将列表中的数字改为1。如果它有一个1,我将它改为2
这是可行的,但我想问,是否有人能想出一种仍然符合这一标准的改进方法。这就是看似显而易见的xor解决方案失败的条件。以下是我所做工作的简化版本:
def encode(pic_data, file_data):
"""encode pic_data with the information stored in file_data"""
# file data is shorter than pic_data, I test for it in the real code
new_pic_data = pic_data.copy()
for i in range(len(file_data)):
# I add 1 to the value of 0 or 1, because I need to be able to
# distinguish 0 from nothing
data_value = int(file_data[i]) + 1
# rgb max value is 255, data_value can be 1 or 2
if new_pic_data[i] >= 253:
data_value *= -1
new_pic_data[i] += data_value
return new_pic_data
def decode(pic_data_original, pic_data_modified):
"""
extract a binary string from the differences between the input
data sets
"""
# both data sets have to be the same length
new_file_data = [abs(pic_data_original[i] - pic_data_modified[i]) - 1
for i in range(len(pic_data_original))]
# the test at the end of this makes sure we do not use locations
# where no data was stored
return ''.join(str(i) for i in new_file_data if i >= 0)
binary_string = '01100001' # the data to be hidden
flat_rgb_data = [18, 15, 222, 69, 151, 222, 254, 199, 21] # the picture
# [19, 17, 224, 70, 152, 223, 253, 201, 21]
encoded_rgb_data = encode(flat_rgb_data, binary_string)
# getting binary_string back, '01100001'
decoded_data = decode(flat_rgb_data, encoded_rgb_data)
print(decoded_data)
背景,对于感兴趣的人:
我在这里真正做的是一些图像隐写术,我可以将任意文件隐藏到图片中。基本思想是,图片是一系列RGB值,其形式为[(R1,G1,B1),(R2,G2,B2),…]
。我将其平铺成一个列表,得到[R1,G1,B1,R2,G2,B2,…]
。这是上面的flat\u rgb\u数据
然后我读取任何类型的文件,并将字节字符串转换为二进制字符串。如果其中一个字符是'0x61'
,则在上面的二进制字符串中变成'0110001'
encode()
中的列表被重新设置(因为没有更好的术语)并保存为图像。即使并排排列,它与原作之间的色差也很难区分。如果没有原稿,我想不出哪怕是图像被修改了
显然,每个图像都必须在视觉上繁忙,并被视为一个一次性的垫子,这样才能工作。此外,您不能使用internet上的图像=)
正如我上面提到的一个关键标准,我需要能够从无信息中分辨出NULL
字符(00000000
)之间的区别,这是因为某些文件格式以有意义的方式使用NULL
字符。通常,当涉及到文本时,人们会忽略这一点,因为您可以安全地删除所有的NULL
s。但作为一个例子,如果从MS Word文档中删除NULL
s,Word将无法再打开它
无论如何,谢谢你的帮助。解决方案:永远不要使用MS Word,反正这是废话!:)
更严重的是,如果我很好地理解你的情况,如果你不使用你的想法,你所面临的唯一问题就是你不知道可能有多少个尾随空。(您仍然可以在文档的“内部”检测到它们。)一个肮脏的解决方案(如果恼人的格式对额外的空值感到满意的话)就是假设所有尾随的0实际上都在为空值编码
一个更好的解决方案是:你能在代码开始的时候以某种方式对后面的空值进行编码吗?例如,如果您知道您的尾随空数从未超过256个,则分配第一个字节对该数字进行编码?这一想法归功于Julien Bernu;我希望他能充实这个想法,并将其作为一个答案发布出来,但已经有一段时间了,所以我决定实施它,这样其他人就可以从这个想法中受益
我不认为这是一个比我原来的算法更好的策略,但它确实解决了我的具体问题,所以值得考虑
优点:
- 修改每个颜色值的最大值为+/-1(而不是+/-2)
- 保留区分
NULL
和00000000
缺点:
- 打破算法对称性(现在必须跟踪哪个图像是原始图像,或在修改后的图像中进行标记)
- 无法使用具有最大或最小颜色值(0或255)的图像部分,具体取决于与该颜色值对齐的位
下面是经过修改的简化示例。注意,为了存储信息,我不得不在图像数据中添加另一个像素,因为有一些0和255的值
def encode(pic_data, file_data):
"""encode pic_data with the information stored in file_data"""
# file data is shorter than pic_data, I test for it in the real code
# would also need to make sure that the length of pic_data is greater than
# the length of file_data by the number of 0s and 255s in it, to be safe
new_pic_data = pic_data.copy()
offset = 0
for i in range(len(file_data)):
# Now, 1 is 1 and 0 is -1, which still allows us to
# distinguish 0 from nothing
data_value = 1 if file_data[i] == '1' else -1
# rgb max value is between 0 and 255
while pic_data[i + offset] == 0 and data_value == -1:
offset += 1
while pic_data[i + offset] == 255 and data_value == 1:
offset += 1
new_pic_data[i + offset] += data_value
return new_pic_data
def decode(pic_data_original, pic_data_modified):
"""
extract a binary string from the differences between the input
data sets
"""
# both data sets have to be the same length
new_file_data = ['1' if (pic_data_modified[i] - pic_data_original[i] == 1)
else '0' if (pic_data_modified[i] - pic_data_original[i] == -1)
else ''
for i in range(len(pic_data_original))]
return ''.join(i for i in new_file_data)
binary_string = '01100001' # the data to be hidden
flat_rgb_data = [18, 15, 255, 0, 151, 0, 254, 199, 21, 180, 105, 205] # the picture
# [17, 16, 255, 1, 150, 0, 253, 198, 20, 181, 105, 205]
encoded_rgb_data = encode(flat_rgb_data, binary_string)
# getting binary_string back, '01100001'
decoded_data = decode(flat_rgb_data, encoded_rgb_data)
print(decoded_data)
Word只是一个随机的例子(我想你知道=)。很多文件格式都使用NULL。无论如何,我也想到了跟踪跟踪空值的想法,但在我的实际程序中,我半随机地将数据沿图像分布(担心如果图像都是前加载的,那么就更容易判断图像是否已被修改)。这意味着我的价值观中没有任何信息。尽管如此,还是要投票支持这个好主意。即使你使用了半随机洗牌,解码器也必须知道该洗牌才能解码。一旦改变了洗牌方式,就不会再有任何信息值散布在各处。因此,真正重要的是尾随的空值。我现在这样做,解码器不需要知道任何东西,因为我区分0和“无信息”。我明白了,你不会随机化顺序,只会随机化位置。好的,你可以做一件简单的事情来避免(使用+2和-2)代码0和-1以及+1来保持绝对差更小。显然,像素为0时不能编码00000000,像素为255时不能编码11111111,但是你可以相应地选择你的图像和编码像素:有一个只有几个0和255像素的图像和一个半随机选择的编码像素来避免这些像素。你也可以使用像素对:第一个像素以随机绝对差1表示下一个正在编码,下一个像素以xor编码。所以当你解码的时候,你扫描你的图像直到下一个修改的像素,然后取下一个像素的xor来提取你的信息位,然后你重复。有一些事情我不明白。XOR在代码中的何处实现?当您可以使用不同的方法从修改后的图像中提取信息时,为什么要使用原始图像来检测差异?使用原始图像和修改后的图像是您项目中的一项要求,还是因为缺少更好的方法而想到的