thearonimperial
thearonimperial

Reputation: 107

AES: Input strings must be a multiple of 16 in length

I want to make a script to decrypt my filess, but when I try to run my script then show me this message , how can I fix it?

Traceback (most recent call last): File "F:\bug_bounty\decrypt.py", line 46, in File "F:\bug_bounty\decrypt.py", line 24, in decrypt File "C:\Python27\lib\site-packages\Crypto\Cipher\blockalgo.py", line 295, in decrypt return self._cipher.decrypt(ciphertext) ValueError: Input strings must be a multiple of 16 in length

from Crypto.Hash import SHA256
from Crypto.Cipher import AES
import os
import random
import sys


def decrypt(key, filename):
    outFile = os.path.join(os.path.dirname(filename),
                           os.path.basename(filename[11:]))
    chunksize = 64 * 1024
    with open(filename, 'rb') as infile:
        filesize = infile.read(16)
        IV = infile.read(16)

        decryptor = AES.new(key, AES.MODE_CBC, IV)

        with open(outFile, 'wb') as outfile:
            while True:
                chunk = infile.read(chunksize)
                if len(chunk) == 0:
                    break

                outfile.write(decryptor.decrypt(chunk))

            outfile.truncate(int(filesize))


def allfiles():
    allFiles = []
    for (root, subfiles, files) in os.walk(os.getcwd()):
        for names in files:
            allFiles.append(os.path.join(root, names))

    return allFiles


password = 'M4st3rRul3zs'
files = allfiles();
for filename in files:
    if os.path.basename(filename).startswith("(encrypted)"):
       print "%s is already encrypted" %filename
       pass

    else:  
        decrypt(SHA256.new(password).digest(), filename)
        print "Done decrypting %s" %filename
        """os.remove(filename)"""

Upvotes: 8

Views: 31294

Answers (4)

Sawan Chauhan
Sawan Chauhan

Reputation: 791

AES works with blocks of 16 chars. This how you can add extra padding

import random
import string
plaintext = "Encrypt me"
encryptor = AES.new(key, AES.MODE_CBC, iv)

while len(bytes(plaintext, encoding='utf-8')) % 16 != 0:
     plaintext = plaintext + random.choice(string.ascii_letters)

ciphertext = encryptor.encrypt(plaintext)

Upvotes: 1

Mayank Pathela
Mayank Pathela

Reputation: 648

Here is the small trick you could use while encrypting the data if your data size is not large.

plaintext = "some text"
encryptor = AES.new(key, AES.MODE_CBC, iv)
ciphertext = encryptor.encrypt(plaintext*16)

This will ensure that your input data is a multiple of 16. And of course, you would like to get the original data back when decrypting.

cipher = AES.new(key, AES.MODE_CBC, iv)
decrypttext = cipher.decrypt(ciphertext)
decrypttext = decrypttext[0:len(plaintext)]

Now, decrpyttext has your original plaintext.

Upvotes: 7

McGrady
McGrady

Reputation: 11477

From Crypto++ wiki.

The block size is determined by AES::BLOCKSIZE. For AES, this is always 16 bytes

AES is a block cipher, it works on 16-byte (128-bit) blocks. It can't work with data smaller or bigger than 16 bytes. Smaller data needs to be padded until they're 16 bytes, and larger data needs to be split into 16-byte blocks.

Also there are algorithms that help you achieve just that (work on data larger than the cipher's block size), they're called block cipher modes of operation.

Have a look at this How to encrypt more than 16 bytes using AES?

Upvotes: 5

Chankey Pathak
Chankey Pathak

Reputation: 21676

ValueError: Input strings must be a multiple of 16 in length

That is because AES works with blocks of 128 bits (16 chars). You can consider adding padding to fix this.

Upvotes: 2

Related Questions