Python实现LSB算法图片隐写、解密、判断图片是否经过LSB隐写

  • 此处原图片和代码在同一文件夹下,文件名为"circle.png"。

  • 此处写入信息为"明天老地方见"。

  • 此处隐写后的新图片为"new_img.png"

  • 此处使用的秘钥为'She loves to read books at night'的base64编码。

  • 使用Fernet 密钥进行加密,请注意,Fernet密钥需要是 32 字节的base64 编码字符串。

Fernet 密钥会经过这样的转换:key = base64.urlsafe_b64decode(key)

也就是说,有着这样的转换过程:

She loves to read books at night(长度必须为32

↓ base64编码

U2hlIGxvdmVzIHRvIHJlYWQgYm9va3MgYXQgbmlnaDE=(长度为44)

↓ Fernet 密钥的转换 key = base64.urlsafe_b64decode(key)

b'She loves to read books at nigh1'(长度为32)

  • 提供几段长度为32的英文:

  1. This cake is delicious and sweet

  1. She loves to play the piano well

  1. You are a very good friend to me

  1. hello world!!!!!!!!!!!!!!!!!!!!!

  • 可以用这个网站进行在线base64编码:https://www.base64encode.org/

  • 对秘钥错误的情况也进行了处理,可以用上面的长度为32的英文试一下秘钥错误的情况

import base64
import cryptography
from cryptography.fernet import Fernet
from cryptography.fernet import InvalidToken
from stegano import lsb


def encrypt_message(message, key):
    """
    用以加密信息
    :param message: 要加密的明文
    :param key: 密码。应为32字节的base64编码字符串
    :return: 返回加密后的密文
    """
    f = Fernet(key)
    return f.encrypt(message.encode()).decode()


def decrypt_message(encrypted_message, key):
    """
    用以解密信息
    :param encrypted_message: 要解密的密文
    :param key: 密码。应为32字节的base64编码字符串
    :return: 返回解密后的明文
    """
    f = Fernet(key)
    return f.decrypt(encrypted_message.encode()).decode()


def hide_message(original_image, message, key):
    """
    用以向图片写入信息
    :param original_image:原始图像文件的路径
    :param message: 想要写入的明文。字符串
    :param key: 密码。应为32字节的base64编码字符串
    :return:返回一个新的图像文件
    """
    if len(str(key)) != 44:  # 注意int不可以用len(),所以要转换为str
        print("密码格式错误!")
        return None
    encrypted_message = encrypt_message(message, key)  # 加密
    return lsb.hide(original_image, encrypted_message)


def extract_message(stegano_image, key):
    """
    用以解密图像中提取隐藏的信息
    :param stegano_image:需要解密的经过隐写的图片
    :param key:密码。应为32字节的base64编码字符串
    :return:返回解密后的信息
    """
    try:
        if len(str(key)) != 44:  # 注意int不可以用len(),所以要转换为str
            print("密码格式错误!")
            return None
        encrypted_message = lsb.reveal(stegano_image)
        message = decrypt_message(encrypted_message, key)
        return message
    except cryptography.fernet.InvalidSignature:
        # Signature did not match digest
        print("密码错误!")
        return None
    except InvalidToken:
        print("密码错误!")
        return None


def lsb_detection(image_path):
    """
    用以检测图片是否经过LSB隐写。
    当图片没有经过LSB隐写时,程序会报错IndexError: Impossible to detect message.
    所以要捕获该异常
    """
    try:
        message = lsb.reveal(image_path)  # 提取隐藏的信息
        # 如果提取出来的信息不是None或空字符串,那么就返回1;否则就返回0
        if message:
            print("该图片可能经过LSB隐写")
            return 1  # 可能经过了LSB隐写
        else:
            return 0  # 可能没有经过LSB隐写

    except IndexError:  # 捕获IndexError异常
        print("该图片没有经过LSB隐写")
        return 0


my_image = 'circle.png'
text = 'She loves to read books at night'  # 长度为32
my_key = base64.b64encode(text.encode('utf-8')).decode('utf-8')  # 转换为base64编码,转换后长度为44
# Fernet密钥需要是 32 字节的base64 编码字符串。
my_message = '明天老地方见'
my_key_bytes = base64.urlsafe_b64decode(my_key)

# 隐藏信息
new_image = hide_message(my_image, my_message, my_key)
new_image.save('new_img.png')

# 提取信息
extracted_message = extract_message('new_img.png', my_key)
print(extracted_message)

# 检测是否经过LSB隐写
lsb_detection('circle.png')

输出结果:

明天老地方见
该图片没有经过LSB隐写

你可能感兴趣的:(python,开发语言,图像处理)