我正在努力学习隐写术及其实施方法。我查看了Github上的一些代码,但我无法理解代码的以下部分:
def hide(filename, message):
img = Image.open(filename)
binary = str2bin(message) + '1111111111111110'
if img.mode in ('RGBA'):
img = img.convert('RGBA')
datas = img.getdata()
newData = []
digit = 0
temp = ''
for item in datas:
if (digit < len(binary)):
newpix = encode(rgb2hex(item[0],item[1],item[2]),binary[digit])
if newpix == None:
newData.append(item)
else:
r, g, b = hex2rgb(newpix)
newData.append((r,g,b,255))
digit += 1
else:
newData.append(item)
img.putdata(newData)
img.save(filename, "PNG")
return "Completed!"
return "Incorrect Image Mode, Couldn't Hide"
如您所见,作者在将消息(文本)转换为二进制字符串时添加了字符串'1111111111111110'
。为什么他这样做,为什么除了最后一位(0?
答案 0 :(得分:0)
这是一个标记。它们用于标记流中某个部分的开头或结尾。在这种情况下,您可以将其称为end-of-message (EOM)标记,因为它可以让您知道何时停止读取更多位。
标记值的选择取决于它使用的数据。在这种情况下,作者假设消息将是通常的字母和标点符号的字符串,即,他不期望任何扩展的ascii代码(128-255)。由于这些代码不会出现在消息中,因此他选择了255和254的串联作为他的标记。
您可以通过隐藏消息'abc\xff\xfedef'
('\xff'
和'\xfe'
只是ascii代码255和254的字符串值来欺骗此系统。在遇到这些值时,提取将把它们解释为EOM信号并停止。因此,您只能返回'abc'
。更多序列可以具有相同的效果,例如字符串'_\xff\xc4'
。
01011111 11111111 11000100
| <-- this --> |
这里我们在仅检索3位后过早地结束提取过程。根据解码器如何准备将这些位转换为消息字符串,它可能会引发错误或返回完全垃圾。
一般来说,当您可以保证在标记本身出现之前的其他任何地方都找不到此序列时,您可以使用标记来指示某个部分的开头/结尾。如果你不能保证,一个可行的选择是在部分(header)的开头添加几个比特来告诉你比特流的长度。