详细分析LSB 隐写术的原理、方法 | 附基本Demo

1. 基本知识

实现图片隐写的基本方法是利用图片的像素数据将信息嵌入其中,同时尽可能保持图片的视觉效果不变

基于 LSB(Least Significant Bit,最低有效位)隐写术:将数据嵌入到图片的像素值的最低有效位

基本原理如下:

  • 编码过程:将要嵌入的信息(二进制数据)替换到图片像素值的最低有效位中
    对 RGB 图片,每个通道可以分别嵌入数据
  • 解码过程:从图片像素的最低有效位中提取信息,并将其还原为原始数据

但是他也有缺点:

  • 容量有限:嵌入信息的量受限于图片的分辨率和像素通道数量
  • 易受图像处理(如压缩、滤波)的影响

总结的表格如下:

类别描述
基本定义LSB 隐写术是一种通过修改数字文件(如图像、音频或视频)中每个数据单元的最低有效位来嵌入隐写信息的方法
适用范围最常用于图像隐写(例如 BMP、PNG 格式),因为这些格式通常无压缩或无损压缩,且对人眼不易察觉嵌入信息的细微变化
原理利用数字文件的冗余特性(如图像像素值、音频采样值),将隐写信息存储到文件数据的最低有效位中,改变的幅度足够小以不被人察觉
示例分析原始二进制像素值:10101101
嵌入隐写信息后:10101100
此处修改了最低位 1→0,人眼无法察觉像素值的细微变化
优点实现简单,效率高
对文件的质量影响较小
可在无损压缩图像中保持高隐写容量
缺点容易受到压缩算法(如 JPEG)的破坏
嵌入容量有限(仅与像素数或数据单元数相关)
安全性较低,容易被简单分析或检测工具发现
嵌入过程1. 选择载体文件(如图像)
2. 将需要隐藏的信息转换为二进制
3. 替换载体文件数据的最低有效位为隐写信息的二进制数据
提取过程1. 读取载体文件的最低有效位数据
2. 还原二进制数据为隐写信息
适用场景信息隐藏与传递
数字版权保护
水印嵌入
抗攻击性对简单篡改或噪声较敏感
可结合加密技术提高安全性(例如对嵌入信息进行加密后再写入)
扩展方法LSB-M(多位隐写):替换最低的多位数据以增加嵌入容量
结合压缩抗性技术,如差值扩展(DE)

具体的文字Demo如下:

在图像隐写中,图像由像素组成,每个像素通常由红、绿、蓝(RGB)三种颜色通道的值表示,每个通道用 8 位二进制数表示
例如,一个像素的 RGB 值可能是 (123, 234, 56),其二进制表示为:
R: 01111011
G: 11101010
B: 00111000

LSB 隐写术通过修改每个通道的最低有效位(最后一位)来嵌入隐写信息。对于上述像素,嵌入数据后可能变为:
R: 01111010
G: 11101011
B: 00111001

2. Demo

  1. 编码部分:
    图片数据转换为 NumPy 数组进行操作
    嵌入的数据被插入到像素值的最低有效位
    添加了 1111111111111110 作为结束标志,用于解码时识别信息终止

  2. 解码部分
    从图片中提取像素的最低有效位,重组为二进制字符串
    根据二进制字符串恢复嵌入的信息

基本的测试Demo如下:

from PIL import Image
import numpy as np

def encode_image(input_image_path, output_image_path, message):
    """
    将信息编码到图片中。
    :param input_image_path: 输入图片路径
    :param output_image_path: 输出图片路径
    :param message: 要嵌入的文本信息
    """
    # 打开图片并转换为 NumPy 数组
    image = Image.open(input_image_path)
    image_array = np.array(image)

    # 将信息转换为二进制字符串
    binary_message = ''.join(format(ord(char), '08b') for char in message)
    binary_message += '1111111111111110'  # 添加结束标志

    # 将消息嵌入图片
    flat_pixels = image_array.flatten()
    if len(binary_message) > len(flat_pixels):
        raise ValueError("信息太长,无法嵌入到图片中。")

    for i in range(len(binary_message)):
        flat_pixels[i] = (flat_pixels[i] & ~1) | int(binary_message[i])

    # 将修改后的像素数组还原为图片
    encoded_image = flat_pixels.reshape(image_array.shape)
    encoded_image = Image.fromarray(encoded_image.astype(np.uint8))
    encoded_image.save(output_image_path)
    print(f"信息已嵌入到图片中,保存为 {output_image_path}。")


def decode_image(encoded_image_path):
    """
    从图片中解码信息。
    :param encoded_image_path: 含有嵌入信息的图片路径
    :return: 解码出的文本信息
    """
    # 打开图片并转换为 NumPy 数组
    image = Image.open(encoded_image_path)
    image_array = np.array(image)

    # 提取二进制数据
    flat_pixels = image_array.flatten()
    binary_message = ''.join(str(flat_pixels[i] & 1) for i in range(flat_pixels.size))

    # 将二进制数据转换为文本
    chars = []
    for i in range(0, len(binary_message), 8):
        byte = binary_message[i:i+8]
        if byte == '11111111':  # 检测结束标志
            break
        chars.append(chr(int(byte, 2)))

    return ''.join(chars)


# 测试
if __name__ == '__main__':
    input_image = 'dog.jpg'  # 替换为实际图片路径
    output_image = 'output.png'
    secret_message = "Hello, Steganography!"

    # 编码
    encode_image(input_image, output_image, secret_message)

    # 解码
    decoded_message = decode_image(output_image)
    print("解码出的信息:", decoded_message)

截图如下:

在这里插入图片描述

没有积分的私聊我 看到消息百分百发给你 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、安装提示输入嵌入和被嵌入的文件名字,注意路径问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农研究僧

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值