在 python 中使用 AES 生成 ECB 企鹅

Produce the ECB penguin with AES in python

我想加密图像中的数据,但生成的密文仍然是有效图像。我在 python 中使用 AES 加密图像,然后,我替换文件中的 header,但是 windows 无法打开加密图像。

代码

def encrypt_file(self, in_filename, out_filename):
    filesize = os.path.getsize(in_filename)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(self.key, AES.MODE_ECB, iv)
    chunksize = 64 * 1024
    with open(in_filename, 'rb') as infile:
        with open(out_filename, 'wb') as outfile:
            outfile.write(struct.pack('<Q', filesize))
            outfile.write(iv)

            while True:
                chunk = infile.read(chunksize)
                if len(chunk) == 0:
                    break
                elif len(chunk) % 16 != 0:
                    chunk += ' ' * (16 - len(chunk) % 16)
                cifrado = base64.b64encode(cipher.encrypt(chunk))
                print cifrado
                outfile.write(cipher.encrypt(chunk))

我想要这样的效果: The ECB Penguin

简单来说:

  1. 抓取.BMP格式的原图

  2. 保持原始 BMP header 未加密。

  3. 只加密图片,不加密 header。

  4. 将未加密的原图header放回加密后的图片前面

如果加密为图像大小添加了一些填充字节,您可能需要稍微调整 header。

PyCrypto and the Python Image Class 在处理图像和 AES 加密方面有非常有用的示例。

此实现仅适用于具有特定特征的 BMP 图像。要使此解决方案起作用,图像必须具有的主要特征是它的大小必须是 16 字节的倍数(对于加密部分,AES ECB 在 16 字节块上运行)。您可以改进它以接受更多的图像格式并填充到 16 字节的倍数:)

如果您不提供图片,系统会自动从网络下载合适的图片。

im_show 来自 Image 已知会在某些平台上引起问题。我在 Ubuntu 14.10 发行版上对此进行了测试,没有 运行 出现任何问题。这是在 Python 2.7 上测试的,我仍在研究我的可移植性技能(你没有在你的问题中指定 Python 版本,所以......)

#!/usr/bin/python
import binascii, os.path, urllib, random, Image
from Crypto.Cipher import AES

class ECBPenguin(object):
    '''
    A penguin class
    '''
    def __init__(self, img_clr=""):
        if not img_clr:
            self.__demo_image__()
            self.img_clr = "tux_clear.bmp"
        else:
            self.img_clr = img_clr
        self.__get_header__()

    def __demo_image__(self):
        ''' 
        Downloads a TUX image compatible for this program: square and with size multiple of 16
        '''
        print "Downloading image..."
        image = urllib.URLopener()
        image.retrieve("http://fp-games.googlecode.com/svn/trunk/CodeWeek1/graviTux/data/tux.bmp","tux_clear.bmp") 

    def __get_sizes__(self, dibheader):
        # Get image's dimensions (at offsets 4 and 8 of the DIB header)
        DIBheader = []
        for i in range(0,80,2):
            DIBheader.append(int(binascii.hexlify(dibheader)[i:i+2],16))
        self.width = sum([DIBheader[i+4]*256**i for i in range(0,4)])
        self.height = sum([DIBheader[i+8]*256**i for i in range(0,4)])

    def __get_header__(self):
        '''
        Read BMP and DIB headers from input image and write them to output image
        '''
        f_in = open(self.img_clr, 'rb')
        # BMP is 14 bytes
        bmpheader = f_in.read(14)
        # DIB is 40 bytes
        dibheader = f_in.read(40)
        self.__get_sizes__(dibheader)
        self._bmpheader = bmpheader
        self._dibheader = dibheader
        f_in.close()

    def encrypt(self, img_enc = "tux_enc.bmp", key = '0123456789abcdef'):
        '''
        Encrypt the my_penguin
        '''
        self.img_enc = img_enc
        f_in = open(self.img_clr, 'rb')
        f_out = open(img_enc, 'wb')
        f_out.write(self._bmpheader)
        f_out.write(self._dibheader)
        row_padded = (self.width * self.height * 3)
        image_data = f_in.read(row_padded)
        cleartext =  binascii.unhexlify(binascii.hexlify(image_data))

        # Initialization Vector
        IV = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
        # AES ECB mode
        mode = AES.MODE_ECB
        # Encryptor
        encryptor = AES.new(key, mode, IV=IV)
        # Perform the encryption and write output to file
        f_out.write(encryptor.encrypt(cleartext))
        f_in.close()
        f_out.close()

    def show_clr(self):
        '''
        Display cleartext penguin
        '''
        im = Image.open(self.img_clr)
        im.show()

    def show_enc(self):
        '''
        Display ciphertext penguin
        '''
        im = Image.open(self.img_enc)
        im.show()

def main():
    my_penguin = ECBPenguin()
    my_penguin.show_clr()
    my_penguin.encrypt()
    my_penguin.show_enc()

if __name__ == "__main__":
    main()

初始和加密图像如下所示:

没找到和your link一样的图片,但是ECB的弱点还是有的!