Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在数字列表中隐藏二进制值_Python_Steganography - Fatal编程技术网

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在代码中的何处实现?当您可以使用不同的方法从修改后的图像中提取信息时,为什么要使用原始图像来检测差异?使用原始图像和修改后的图像是您项目中的一项要求,还是因为缺少更好的方法而想到的