此处原图片和代码在同一文件夹下,文件名为"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的英文:
This cake is delicious and sweet
She loves to play the piano well
You are a very good friend to me
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隐写