我正在使用pycryptodome
模块及其AES功能来加密一些数据。但是,我需要为以后可以检索的AEScipher
生成一个密钥。该项目以图像的形式存储所有私有数据(包括密钥(。基本上,我们使用像素数组并使用PIL
创建图像并使用getdata()
函数检索pixel_list。
要创建映像:-
array = numpy.array(pixels, dtype = numpy.uint8)
new_image = Image.fromarray(array)
new_image.save('user_key.png')
请注意,像素是整数元组列表的列表[[(...), (...)], [(...), (...)], ...]
这是携带键的对象 要从映像中获取密钥:-
im = Image.open(image_path)
return list(im.getdata())
现在我无法直接存储AES key
,假设我使用加密模块的Random.get_random_bytes(AES.key_size)
生成它。
如何生成加密安全密钥,但也要使用pixels
中的密钥之一来检索它,就像在整数元组中一样?
编辑:-
详细来说,像素对象是整数元组列表的列表,每个元组包含 3 个整数,每个整数的范围可以从 0 到 255。像素对象的第 0 个索引可能如下所示-[(69, 147, 245), (120, 212, 198), ...]
我所指key_list
对象实际上是list(im.getdata())
。这是一个整数元组的列表,每个元组包含 3 个整数,每个整数的范围可以从 0 到 255。这看起来像这样——[(69, 147, 245), (120, 212, 198)....]
因此,key_list的第 0 个索引将(69, 147, 245)
我需要将 AES 密钥与这些值存储相同。理想情况下,我想将 AES 密钥存储为 3 个整数的元组,范围从 0 到 255。所以是的,我需要将 AES 密钥转换为元组,然后将其存储在pixels
中。
另一个关键细节是,元组包含 3 个整数,因为它们分别表示创建图像的 RGB 值。我相信元组也可以用 4 个整数来表示 RGBA 值。这样就可以解决 3 的倍数问题。
但还有另一个问题。pixels
中的每个元组实际上是通过[i for i in itertools.product(range(256), repeat=3)]
生成的。为了生成一个由 4 个整数而不是 3 个整数组成的元组,我必须将repeat=3
更改为repeat=4
,这将引发 MemoryError。
这是一个函数,可用于将字节字符串中的值划分为指定大小的元组。字节字符串首先打印为整数列表,然后是与之对应的元组列表。请注意,在示例中,最后一个元组除以 3 时的最后两个值如何用零填充,因为字节字符串长度 (16( 不是该元组的倍数。将其划分为大小为 4 的元组时不会发生这种情况(因此没有附加填充值(。
另请注意,下面的grouper()
函数是itertools
文档中同名配方的略有不同的实现。
from itertools import zip_longest
def grouper(n, iterable, fillvalue=None):
"s -> (s0, s1...sn-1), (sn, sn+1...s2n-1), (s2n, s2n+1...s3n-1), ..."
return zip_longest(*[iter(iterable)]*n, fillvalue=fillvalue)
aes_key = b'x80inxbex06bx8fx8fZ}l-xb4jxb5x1f'
ints = list(aes_key)
print(ints)
tuples = list(grouper(3, aes_key, fillvalue=0))
print(tuples)
tuples = list(grouper(4, aes_key, fillvalue=0))
print(tuples)
输出:
[128, 105, 110, 190, 6, 98, 143, 143, 90, 125, 108, 45, 180, 106, 181, 31]
[(128, 105, 110), (190, 6, 98), (143, 143, 90), (125, 108, 45), (180, 106, 181), (31, 0, 0)]
[(128, 105, 110, 190), (6, 98, 143, 143), (90, 125, 108, 45), (180, 106, 181, 31)]
由于您似乎想用这些数据制作图像,因此您可能仍需要根据图像每行中的像素数进一步格式化该数据。
您可以将元组列表转换回字节字符串,如下所示:
# To convert a list of tuples back into a byte string.
from itertools import chain
print(bytes(chain.from_iterable(tuples)))
输出:
b'x80inxbex06bx8fx8fZ}l-xb4jxb5x1f'
但是,如果没有添加填充值,则这只会与原始字节字符串相同(就像使用 4 元组的情况一样(。