【问题标题】:How to create image from binary string如何从二进制字符串创建图像
【发布时间】:2017-06-02 19:08:39
【问题描述】:

我从文件图像中读取二进制文件,每个 128 字节,并使用 rsa 加密。但加密后我无法从二进制创建图像。我创建了函数生成密钥 rsa。我将二进制转换为 int 以进行加密

from PIL import Image
import KeyRSA
import RsaMath

pub, piv = KeyRSA.GenerateRsaKey(size=1024)
n, e = pub

with open("hinh.png", "rb") as infile:
    data = infile.read()
step = 128
cipher_data = []
for i in range(0, len(data), step):
    value = data[i:i+step]
    m = RsaMath.OS2IP(value)
    c = pow(m, e, n)
    cipher_data.append(RsaMath.I2OSP(c, 128))

cipher_data = "".join(cipher_data)

im = Image.open("hinh.png")
W, H = im.size
img = Image.frombytes("RGB", (W,H), cipher_data)
img.show()e here

【问题讨论】:

  • KeyRSA 和 RsaMath 来自哪里?您的问题是因为您正在加密 PNG 文件的字节,而不是原始像素数据。但是如果不知道 KeyRSA 和 RsaMath 模块函数的作用,就很难给出更具体的答案。
  • 嗨。 KeyRSA 只是为 RSA 生成密钥。 RsaMath 包含 IO2SP 和 O2ISP 函数,用于将八位字节字符串转换为数字,将数字转换为八位字节字符串。
  • 所以使用PIL打开源图片,使用图片.tobytes方法获取原始像素字节数据。如果它是大小为 WxH 的 RGB 图像,您将获得 3*W*H 字节。我假设你的 RSA 编码算法输出的字节数与你只提供整个 128 字节块的字节数相同。
  • 所以。当我加密时。我想从字节创建图像。怎么做。对不起,我不好
  • img = Image.frombytes("RGB", (W,H), cipher_data) 将在 cipher_data 包含 恰好 3*W*H 字节时工作。 RSA 加密数据的生成图像只是看起来随机的噪声,但我认为这就是您想要的。

标签: python image rsa


【解决方案1】:

由于我无法访问 KeyRSA 和 RsaMath,我决定使用 pycrypto 包。原始 RSA 加密不安全,而且速度很慢,因此此代码使用 AES,它速度快,而且在具有 128 字节块的块模式下使用非常安全。

下面的代码不是从文件中读取图像,而是生成一个简单的两色图像。然后对其进行加密,将加密数据转换为图像,然后将其显示并保存为 PNG。然后它会解密加密的数据以恢复原始图像。

加密过程是使用 128 字节块执行的,因此如果您真的想要这样做,您可以轻松地将其调整为您的 RSA 加密算法。但是,一步执行加密更有效;我已经包含了一个注释掉的行来说明如何做到这一点。

#!/usr/bin/env python3

''' Create a simple image and encrypt it with AES

    See https://stackoverflow.com/q/44314026/4014959

    Written by PM 2Ring 2017.06.02
'''

from PIL import Image
from Crypto.Cipher import AES

def color_square(size, colors):
    ''' Make a square that fades diagonally
        from the 1st color to the 2nd color
    '''
    m = 255.0 / (2 * size - 2)
    r = range(size)
    mask = bytes(int(m * (x + y)) for y in r for x in r)
    mask = Image.frombytes('L', (size, size), mask)
    imgs = [Image.new('RGB', (size, size), color=c) for c in colors]
    return Image.composite(imgs[0], imgs[1], mask)

# Create a simple image
size = 128
img = color_square(size, ('red', 'blue'))
img.show()

# Extract the raw pixel data from the image
src_data = img.tobytes()
print('Original length:', len(src_data), size*size*3)

# Create an AES cipher object
key = b'This is a key123'
iv = b'This is an IV456'
crypto = AES.new(key, AES.MODE_CBC, iv)

# Encrypt the data in 128 byte chunks
blocks = []
for i in range(0, len(src_data), 128):
    blocks.append(crypto.encrypt(src_data[i:i+128]))
cipher_data = b''.join(blocks)

# We could actually encrypt it in one step with
#cipher_data = crypto.encrypt(src_data)
print('Encoded length', len(cipher_data))

# Convert the encrypted data to an image & display it
img = Image.frombytes("RGB", (size, size), cipher_data)
img.show()
img.save('redblue_AES.png')

# We need a fresh AES cipher object to do the decoding
crypto = AES.new(key, AES.MODE_CBC, iv)
decoded_data = crypto.decrypt(cipher_data)
print('Decoded length', len(decoded_data))

# Convert the decrypted data to an image & display it
img = Image.frombytes("RGB", (size, size), decoded_data)
img.show()
img.save('redblue.png')

这里是 redblue.png 和 redblue_AES.png

【讨论】:

  • 为什么解密时你没有读取加密的图像。当我读取加密解密的图像时。它不起作用:(
  • @mr.hiep 我没有费心从加密图像中读取字节,因为我已经在cipher_data 中有它们。但是,如果您想从加密图像中提取字节,只需执行cipher_data = img.tobytes(),这与我们从原始图像中提取字节所做的相同。
  • 看我的回答。请告诉我为什么?
  • @mr.hiep 请对您的问题进行任何澄清,而不是发布答案。请记住,这篇文章的作者已经解决了你原来的问题。请停止对他们发表评论以寻求更多帮助。如果您有一个新问题,请花时间提出一个好问题并将其作为一个新问题提出。谢谢。
  • @mr.hiep 您的答案不是答案,而是一个新问题。如果您想在新问题中提出问题,则需要包含一些无法正确解密的测试数据,以便人们可以重现问题。
猜你喜欢
  • 2019-07-28
  • 2019-08-27
  • 2016-02-10
  • 2019-09-15
  • 2015-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-07
相关资源
最近更新 更多