估计的消息长度是您将嵌入的 1 和 0 的总长度。这由标头(可选)和消息流组成。
消息大小(消息流)
这取决于消息的大小以及隐藏方式。通常,您想询问将消息转换为 1 和 0(消息流)时的形式。数字 0-255 和 ASCII 字符每个可以用 8 位表示。最直接的例子包括:
您还可以决定在嵌入之前压缩您的消息,例如使用霍夫曼编码。这应该将您的消息转换为比上述示例更少的位,但您还需要在消息中包含您的解码表,以便收件人可以解码消息。总体而言,即使只有几百个字符,Huffman 压缩也会缩短长度,包括表格。
元数据(标题)
说到元数据,在很多情况下,仅仅嵌入您的消息流是不够的。对于短于最大消息容量的消息流,您有 3 个选项来处理剩余空间:
如果您决定什么都不做,您可能需要告诉收件人他必须阅读多少像素才能提取整个消息,以免继续阅读胡言乱语。您可以说消息流的总位数,或者在提取所有信息之前要读取多少像素。对于前一个选项,倾向于将 32 位用于消息长度,但这可能有点过分了。您可以设置更实际的限制,或采用更动态的方法。
如果你假设你永远不会使用比 1920x1200 灰度图像更大的覆盖,并且 4 位 LSB 嵌入(1920x1200x4 = 9216000
一种更动态的方法是估计表示消息长度的最小位数,例如最多 256 的消息长度为 8 位,最多 512 的消息长度为 9 位,等等。然后将此数字编码为 5 位值,后跟消息长度。例如,如果消息长度为 3546 位,使用 32 位对长度进行编码,则变为 00000000000000000000110111011010。但是使用动态方法,它是 01100 10111011010,其中 01100 是 12 的二进制,也就是说读取后面的 12 位得到消息长度。
如果您的程序将文本和图像都作为秘密消息处理,您还需要告诉收件人秘密的类型。如果您只打算使用上述四种类型,我会使用两位进行编码:纯文本 = 00,二进制图像 = 01,灰度图像 = 10,彩色图像 = 11。
如果密钥是图片,您还需要提供高度和宽度长度。 16x2 位是这里的普遍趋势。但与上面的消息长度类似,您可以使用更实用的东西。例如,您可以期望没有图像的宽度或高度超过 2048 像素长度,因此 11x2 位足以编码此信息。
如果您将密钥嵌入到最后一个 LSB 之外,您的消息长度可能不能被该数字整除。例如,当您嵌入 4 位 LSB 时,消息长度为 301。在这种情况下,您需要用另外 3 个垃圾 1 或 0 填充消息,以便它可以被 4 整除。现在,304 是您报告的消息流,但是在您提取它之后,您可以丢弃最后 3 位。假设您永远不会嵌入超过 7 位 LSB 是合乎逻辑的,因此将 3 位用于填充应该绰绰有余。
根据您选择包含在元数据中的内容,您可以将所有这些内容拼接在一起并将它们称为标题。
示例
让我们做几个例子来看看它的实际效果。我们让标头格式按照消息长度、秘密类型、填充、高度、宽度的顺序(最后两个仅在必要时)。
使用 4 位 LSB 嵌入字符串“Hello World”
消息流为 11 x 8 = 88 位。
88 mod 4 = 0,因此填充为 000(3 位)。
消息长度为 88 = 00111 1011000(12 位)。
秘密类型是文本,所以是 00(2 位)。
估计的消息长度:标头 + 消息流 = (12 + 2 + 3) + 88 = 105 位。
使用 3 位 LSB 嵌入大小为 151 x 256 的灰度图像
消息流为 151 x 256 x 8 = 309248 位。
309248 mod 3 = 2,因此填充为 3-2 = 1 = 001(3 位)。
消息长度为 309249 = 10011 1001011100000000001(24 位)。
秘密类型是灰度图像,所以 10(2 位)。
秘密是图像,因此使用 2 个 16 位数字(32 位)添加宽度和高度。
估计的消息长度:标头 + 消息流 = (24 + 2 + 3 + 32) + 309249 = 309310 位。