python版本3.10
这段代码仅支持隐藏输入英文信息
默认注释了展示R、G、B三层的语句
请注意修改图片路径为你自己的图片所在路径
from PIL import Image
def get_pixel_values(image):
width, height = image.size
pixel_values = list(image.getdata())
if image.mode == 'RGB':
channels = 3
elif image.mode == 'RGBA':
channels = 4
else:
raise ValueError("不支持的图像模式: %s" % image.mode)
pixel_values = [pixel_values[i * width:(i + 1) * width] for i in range(height)]
return pixel_values, channels
def get_channel_image(pixel_values, channel):
return [[pixel[channel] for pixel in row] for row in pixel_values]
def merge_channels(red_channel, green_channel, blue_channel, channels):
pixels = []
for i in range(len(red_channel)):
row = []
for j in range(len(red_channel[i])):
if channels == 3:
pixel = (red_channel[i][j], green_channel[i][j], blue_channel[i][j])
else:
pixel = (red_channel[i][j], green_channel[i][j], blue_channel[i][j], 255)
row.append(pixel)
pixels.append(row)
return pixels
def hide_message(image, message):
pixel_values, channels = get_pixel_values(image)
red_channel = get_channel_image(pixel_values, 0)
green_channel = get_channel_image(pixel_values, 1)
blue_channel = get_channel_image(pixel_values, 2)
message += "EOF" # 为消息添加文件结束标记
message_binary = ''.join(format(ord(i), '08b') for i in message)
# 检查图像是否有足够的容量来隐藏消息
max_message_length = len(red_channel) * len(red_channel[0]) * channels // 8
if len(message_binary) > max_message_length:
raise ValueError("Message too long to hide in image")
# LSB算法
index = 0
for i in range(len(red_channel)):
for j in range(len(red_channel[i])):
if index < len(message_binary):
red_channel[i][j] = (red_channel[i][j] & ~1) | int(message_binary[index])
index += 1
if index < len(message_binary):
green_channel[i][j] = (green_channel[i][j] & ~1) | int(message_binary[index])
index += 1
if index < len(message_binary):
blue_channel[i][j] = (blue_channel[i][j] & ~1) | int(message_binary[index])
index += 1
if index >= len(message_binary):
break
if index >= len(message_binary):
break
merged_pixels = merge_channels(red_channel, green_channel, blue_channel, channels)
merged_image = Image.new(image.mode, image.size)
merged_image.putdata([pixel for row in merged_pixels for pixel in row])
return merged_image
def extract_message(image):
pixel_values, channels = get_pixel_values(image)
red_channel = get_channel_image(pixel_values, 0)
green_channel = get_channel_image(pixel_values, 1)
blue_channel = get_channel_image(pixel_values, 2)
# LSB算法
message_binary = ""
message_hex = ""
for i in range(len(red_channel)):
for j in range(len(red_channel[i])):
message_binary += str(red_channel[i][j] & 1)
if len(message_binary) % 8 == 0:
message_hex += '{:02x}'.format(int(message_binary[-8:], 2))
if message_binary[-8:] == "00000000":
return bytes.fromhex(message_hex).decode('utf-8', 'ignore')
message_hex += '{:02x}'.format(int(message_binary[-8:], 2))
message_binary += str(green_channel[i][j] & 1)
if len(message_binary) % 8 == 0:
message_hex += '{:02x}'.format(int(message_binary[-8:], 2))
message_binary += str(blue_channel[i][j] & 1)
if len(message_binary) % 8 == 0:
message_hex += '{:02x}'.format(int(message_binary[-8:], 2))
return bytes.fromhex(message_hex).decode('gbk')
def attack_image(image):
# 随机改变每个像素的最后一位
pixel_values, channels = get_pixel_values(image)
for i in range(len(pixel_values)):
for j in range(len(pixel_values[i])):
pixel = list(pixel_values[i][j])
for k in range(channels):
pixel[k] ^= 1
pixel_values[i][j] = tuple(pixel)
image_attacked = Image.new(image.mode, image.size)
image_attacked.putdata([pixel for row in pixel_values for pixel in row])
return image_attacked
# 加载图像 <----注意在这里需要你自行设置图片路径!---->
image = Image.open("image_path")
# 分离RGB三层图像并展示
red_channel_image = Image.new("L", image.size)
red_channel_image.putdata([pixel[0] for row in image.getdata() for pixel in [row]])
# red_channel_image.show()
green_channel_image = Image.new("L", image.size)
green_channel_image.putdata([pixel[1] for row in image.getdata() for pixel in [row]])
# green_channel_image.show()
blue_channel_image = Image.new("L", image.size)
blue_channel_image.putdata([pixel[2] for row in image.getdata() for pixel in [row]])
# blue_channel_image.show()
# 将信息隐写入图像
message = "This is a secret message"
steg_image = hide_message(image, message)
steg_image.show()
# 从示例图像中提取信息
extracted_message = extract_message(steg_image)
print("提取到信息: " + extracted_message)
# 攻击示例图像
attacked_image = attack_image(steg_image)
attacked_image.show()
# 检查是否能从被攻击图像中获取信息
try:
extracted_message = extract_message(attacked_image)
print("从被攻击图像中提取到信息: " + extracted_message)
except:
print("未能从被攻击图像中提取到信息")