2015-03-13 2 views
1

Je veux crypter des données dans une image mais le texte chiffré qui en résulte reste une image valide. Je crypte l'image avec AES en python et puis, je remplace l'en-tête dans les fichiers, mais Windows ne peut pas ouvrir l'image cryptée.Produire le pingouin ECB avec AES en python

code

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)) 

Je veux cet effet: The ECB Penguin

+0

Pourriez-vous fournir plus d'informations à ce sujet? Peut-être du code? Votre titre pourrait être un peu plus représentatif aussi – koukouviou

+0

Je modifie ma demande. Merci – davidad

+0

quel format d'image et visionneuse d'image essayez-vous d'utiliser; l'article lié utilisé ppm, qui est un format simple agréable par opposition à par exemple. jpeg ... mais je ne sais pas si Windows est livré avec un lecteur de ppm par défaut. – Foon

Répondre

5

PyCrypto et le Python Image Class avait des exemples très utiles sur le jeu avec les images et le cryptage AES. Cette implémentation fonctionne uniquement avec les images BMP ayant certaines caractéristiques. La principale caractéristique qu'une image doit avoir pour que cette solution fonctionne est qu'elle doit être d'une taille multiple de 16 octets (pour la partie de chiffrement, AES ECB fonctionne sur des blocs de 16 octets). Vous pouvez travailler sur l'amélioration de cette option pour accepter plus de formats d'image et un pad de 16 octets multiples.

Si vous ne fournissez pas d'image, une image appropriée du Web est téléchargée automatiquement.

im_show de Image est connu pour causer des problèmes sur certaines plates-formes. J'ai testé cela sur une distribution Ubuntu 14.10 et je n'ai rencontré aucun problème. Cela a été testé sur Python 2.7, je travaille toujours sur mes compétences portabilité (vous ne spécifiez pas une version Python dans votre question si ...)

#!/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 = 'abcdef'): 
     ''' 
     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() 

Les images initiales et chiffrées ressemblent à ceci:

Plaintext TUX ECB "Encrypted" TUX

Je ne pouvais pas trouver la même image que celle de your link, mais le point de faiblesse de la BCE est toujours fait!

+0

@davidad cette adresse votre problème? – koukouviou

1

En termes simples:

  1. Saisissez la image originale au format .BMP.

  2. Conserver l'en-tête BMP d'origine non chiffré.

  3. Chiffrez uniquement l'image et non l'en-tête.

  4. Replacez l'en-tête non chiffré d'origine devant l'image chiffrée.

Vous devrez peut-être modifier légèrement l'en-tête si le cryptage a ajouté quelques octets de remplissage à la taille de l'image.

+0

merci, mais cette information je sais. Je veux du code ou un pseudo-code. – davidad

+0

Lequel des quatre étapes avez-vous des difficultés? "Pseudocode" couvre un grand nombre de possibilités. Ma réponse pourrait être considérée comme un Pseudocode de très haut niveau. – rossum