从加密图像创建 jpg/png

问题描述

我希望能够转换/显示 AES256 非对称加密图像,即使它看起来很垃圾,我已经阅读了很多关于 SO 的内容,建议删除标题,然后重新附加它们,即使看起来很疯狂它仍然显示它。

重点是我想看看是否可以对使用已知公钥加密的图像数据集执行图像分类。如果我有一张猫的图片,并且我使用完全相同的密钥对其进行加密,那么结果通常是可重现的,并且生成的图像在某种程度上等同于原始图像。

请原谅缺乏代码,我不想用我正在考虑的想法来污染讨论,以便从你们可爱的人那里得到适当的批评 - 我会说我不是加密专家,因此我要求在这里提供建议。

解决方法

有很多选择,但我建议遵循以下准则:

  • 加密图像数据,而不是图像文件。
    如果图像是 100x100x3 字节,请加密 30000 字节(例如不是 img.jpg 文件)。
    (缺点是元数据不会作为加密图像的一部分保存)。
  • 使用无损图像文件格式存储加密图像(例如 PNG 文件格式,而不是 JPEG 格式)。
    JPEG 等有损格式将不可逆转。
  • 将加密图像的分辨率设置为与输入图像相同的分辨率。
    这样你就不需要存储图像标题 - 分辨率被保存。
    您可能需要添加填充,因此以字节为单位的大小是 32 的倍数。

我希望你了解 Python...

这是一个演示编码和解码过程的 Python 代码示例:

import cv2
import numpy as np
from Crypto.Cipher import AES

# https://stackoverflow.com/questions/61240967/image-encryption-using-aes-in-python
key = b'Sixteen byte key'
iv = b'0000000000000000'

# Read image to NumPy array - array shape is (300,451,3)
img = cv2.imread('chelsea.png')

# Pad zero rows in case number of bytes is not a multiple of 16 (just an example - there are many options for padding)
if img.size % 16 > 0:
    row = img.shape[0]
    pad = 16 - (row % 16)  # Number of rows to pad (4 rows)
    img = np.pad(img,((0,pad),(0,0),0)))  # Pad rows at the bottom  - new shape is (304,3) - 411312 bytes.
    img[-1,-1,0] = pad  # Store the pad value in the last element

img_bytes = img.tobytes()  # Convert NumPy array to sequence of bytes (411312 bytes)
enc_img_bytes = AES.new(key,AES.MODE_CBC,iv).encrypt(img_bytes)  # Encrypt the array of bytes.

# Convert the encrypted buffer to NumPy array and reshape to the shape of the padded image (304,3)
enc_img = np.frombuffer(enc_img_bytes,np.uint8).reshape(img.shape)

# Save the image - Save in PNG format because PNG is lossless (JPEG format is not going to work).
cv2.imwrite('enctypted_chelsea.png',enc_img)



# Decrypt:
################################################################################
key = b'Sixteen byte key'
iv = b'0000000000000000'

enc_img = cv2.imread('enctypted_chelsea.png')

dec_img_bytes = AES.new(key,iv).decrypt(enc_img.tobytes())

dec_img = np.frombuffer(dec_img_bytes,np.uint8).reshape(enc_img.shape)  # The shape of the encrypted and decrypted image is the same (304,3)

pad = int(dec_img[-1,0])  # Get the stored padding value

dec_img = dec_img[0:-pad,:,:].copy()  # Remove the padding rows,new shape is (300,3)

# Show the decoded image
cv2.imshow('dec_img',dec_img)
cv2.waitKey()
cv2.destroyAllWindows()

加密图片:
enter image description here

解密图像:
enter image description here


识别加密图像的想法:

  • 计算加密图像的哈希值,并将其与原始图像、keyiv 一起存储在您的数据库中。
  • 获得加密图像后,计算哈希值,然后在数据库中搜索它。
,

我正在使用答案,尽管它不是答案,因为我想展示两张图片来演示。

两张照片均来自我的博客条目 http://javacrypto.bplaced.net/g01-ecb-pinguin/(德语)。

第一张图是ECB模式下AES加密后的图克企鹅:

Tuc penguin after AES ECB encryption

表单仍然存在,您可以“想象”显示的任何内容。

第二张图片是用 AES 在 CBC 模式下加密的,输出看起来像垃圾:

Tuc penguin after AES CBC encryption

结论:如果图片是用 CBC、CTR 或 GCM 等模式加密的,即使您知道正在使用的模式、密钥和初始化向量,您也将始终得到类似于第二张图片的信息。

视觉比较不起作用,抱歉。

要在评论中回答您的问题“您将如何以加密形式显示加密图像”:您无法显示它们,因为通常图片有一个 标题 也会被加密,所以这个信息会丢失。这两张“加密”的图片是通过在加密前剥离头部而形成的,然后图片数据被加密并在头部被添加。