Расшифровка шифрования AES-CBC 128, 192 и 256 в Python 3 с использованием заполнения PKCS # 7

Я много искал в SO полный пример расшифровки шифрования с моим требованием. На самом деле, у меня есть много ссылок и примеров, но ни один из них не работает для меня в режиме AES-192-CBC и AES-256-CBC.

У меня есть следующий пример, который должен работать со всеми типами, но работает только с режимом AES-128-CBC. Я новичок в Python. Может ли кто-нибудь помочь мне, где я ошибаюсь?

Я использую Python 3.4 в Windows и не могу перейти на Python 2.7.

import base64
from Crypto.Cipher import AES

class AESCipher:
    class InvalidBlockSizeError(Exception):
        """Raised for invalid block sizes"""
        pass

    def __init__(self, key, block_size=16):
        if block_size < 2 or block_size > 255:
            raise AESCipher.InvalidBlockSizeError('The block size must be between 2 and 255, inclusive')
        self.block_size = block_size
        self.key = key
        self.iv = bytes(key[0:16], 'utf-8')
        print(self.key)
        print(key[0:16])

    def __pad(self, text):
        text_length = len(text)
        amount_to_pad = self.block_size - (text_length % self.block_size)
        if amount_to_pad == 0:
            amount_to_pad = self.block_size
        self.pad = chr(amount_to_pad)
        return text + self.pad * amount_to_pad

    def __unpad(self, text):
        #pad = ord(text[-1])
        #return text[:-pad]
        text = text.rstrip(self.pad)
        return text

    def encrypt( self, raw ):
        raw = self.__pad(raw)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        return base64.b64encode(cipher.encrypt(raw)) 

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv )
        return self.__unpad(cipher.decrypt(enc).decode("utf-8"))

e = AESCipher('1234567812345678', 16)
#e = AESCipher('123456781234567812345678', 24)
#e = AESCipher('12345678123456781234567812345678', 32)
secret_data = "hi"
enc_str = e.encrypt(secret_data)
print('enc_str: ' + enc_str.decode())
dec_str = e.decrypt(enc_str)
print('dec str: ' + dec_str)

Хотя этот код шифрует данные с помощью 192- и 256-битного шифрования и успешно расшифровывает их, но другие мои приложения .Net и Ruby могут расшифровывать только данные, которые были зашифрованы с использованием 128-битного шифрования.

Примечание. Приложения .Net и Ruby успешно протестированы друг с другом и с онлайн-инструментом шифрования со всеми типами шифрования.

Обратите внимание, что для моего приложения требуется режим AES-CBC и заполнение PKCS#7, и оно должно работать на Python 3.4.


person Nilesh Vora    schedule 23.09.2016    source источник


Ответы (1)


Заставил работать, заполнив 16 байт для любых типов шифрования. Для этого я использовал AES.block_size, который по умолчанию равен 16 для AES.

import base64
from Crypto.Cipher import AES

class AESCipher:
    class InvalidBlockSizeError(Exception):
        """Raised for invalid block sizes"""
        pass

    def __init__(self, key):
        self.key = key
        self.iv = bytes(key[0:16], 'utf-8')
        print(self.key)
        print(key[0:16])

    def __pad(self, text):
        text_length = len(text)
        amount_to_pad = AES.block_size - (text_length % AES.block_size)
        if amount_to_pad == 0:
            amount_to_pad = AES.block_size
        pad = chr(amount_to_pad)
        return text + pad * amount_to_pad

    def __unpad(self, text):
        pad = ord(text[-1])
        return text[:-pad]

    def encrypt( self, raw ):
        raw = self.__pad(raw)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        return base64.b64encode(cipher.encrypt(raw)) 

    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv )
        return self.__unpad(cipher.decrypt(enc).decode("utf-8"))

e = AESCipher('1234567812345678', 16)
#e = AESCipher('123456781234567812345678', 24)
#e = AESCipher('12345678123456781234567812345678', 32)
secret_data = "hi"
enc_str = e.encrypt(secret_data)
print('enc_str: ' + enc_str.decode())
dec_str = e.decrypt(enc_str)
print('dec str: ' + dec_str)
person Nilesh Vora    schedule 23.09.2016
comment
Я не понимаю этот ответ. Вы изменили self.block_size на 16, но block_size было инициализировано 16, так что ничего не должно было измениться. Вы изменили что-то еще? - person Artjom B.; 23.09.2016
comment
пожалуйста, прочитайте вопрос полностью. Я написал, что когда я взял размер блока 24 и 32, он не работал. потому что ранее черный размер инициализировался тем, что передается в аргументе. См. функцию __pad и прокомментированный код man. - person Nilesh Vora; 24.09.2016
comment
Я понимаю. Я не видел ваш закомментированный код. Тем не менее, 256 в AES-256 всегда означает размер ключа, а не размер блока, потому что, как вы, вероятно, уже узнали, AES имеет единственный фиксированный размер блока 16 байт, и вы можете получить его с помощью AES.block_size в pyCrypto. Вам не нужно жестко кодировать это. Поскольку вам не нужно передавать размер блока во время инициализации, вы должны включить этот код в свой ответ (пропингуйте меня, когда закончите, чтобы я мог удалить свой отрицательный голос). - person Artjom B.; 24.09.2016
comment
Небезопасно использовать (часть) ключа в качестве IV: crypto.stackexchange.com/questions/16161/ - person pors; 04.02.2018
comment
Функция _pad излишне расширяет текст как amount_to_pad, потому что n % m никогда не будет равно m. Также плюс 1, чтобы прокомментировать IV, исходящий от ключа, который является неудачным. - person caffeinate_me; 05.07.2019