AttributeError: у объекта 'bytes' нет атрибута 'encode' - PullRequest
0 голосов
/ 24 февраля 2020

Попытка импортировать код из python2 в python 3, и эта проблема возникает

    <ipython-input-53-e9f33b00348a> in aesEncrypt(text, secKey)
     43 def aesEncrypt(text, secKey):
     44     pad = 16 - len(text) % 16
---> 45     text = text.encode("utf-8") + (pad * chr(pad)).encode("utf-8")
     46     encryptor = AES.new(secKey, 2, '0102030405060708')
     47     ciphertext = encryptor.encrypt(text)

AttributeError: у объекта 'bytes' нет атрибута 'encode'

Если я удаляю .encode("utf-8"), ошибка «не может быть связана с байтами». Видимо pad*chr(pad) кажется байтовой строкой. Он не может использовать encode()

    <ipython-input-65-9e84e1f3dd26> in aesEncrypt(text, secKey)
     43 def aesEncrypt(text, secKey):
     44     pad = 16 - len(text) % 16
---> 45     text = text.encode("utf-8") + (pad * chr(pad))
     46     encryptor = AES.new(secKey, 2, '0102030405060708')
     47     ciphertext = encryptor.encrypt(text)

TypeError: невозможно объединить str с байтами

Однако странная вещь в том, что если я просто попробую часть по , encode () работает нормально.

text = { 'username': '', 'password': '', 'rememberLogin': 'true' }
text=json.dumps(text)
print(text)
pad = 16 - len(text) % 16 
print(type(text))
text = text + pad * chr(pad) 
print(type(pad * chr(pad)))
print(type(text))
text = text.encode("utf-8") + (pad * chr(pad)).encode("utf-8") 
print(type(text))

{"username": "", "password": "", "rememberLogin": "true"}
<class 'str'>
<class 'str'>
<class 'str'>
<class 'bytes'>

Ответы [ 3 ]

0 голосов
/ 24 февраля 2020

Если вы не знаете, является ли строковидный объект строкой Python 2 (байтами) или строкой Python 3 (юникодом). У вас может быть конвертер c.

Python3 shell:

>>> def to_bytes(s):
...     if type(s) is bytes:
...         return s
...     elif type(s) is str or (sys.version_info[0] < 3 and type(s) is unicode):
...         return codecs.encode(s, 'utf-8')
...     else:
...         raise TypeError("Expected bytes or string, but got %s." % type(s))
...         
>>> to_bytes("hello")
b'hello'
>>> to_bytes("hello".encode('utf-8'))
b'hello'

При Python 2 оба эти выражения оцениваются как True: type("hello") == bytes и type("hello") == str. И type(u"hello") == str оценивается как False, тогда как type(u"hello") == unicode равно True.

Вкл. Python 3 type("hello") == bytes равно False, а type("hello") == str равно True. И type("hello") == unicode вызывает исключение NameError, поскольку unicode не определено в оболочке 3.

Python 2:

>>> to_bytes(u"hello")
'hello'
>>> to_bytes("hello")
'hello'
0 голосов
/ 25 февраля 2020

Благодаря @Todd он решил проблему. (pad * chr(pad)) - это байты, в то время как проблема aesEncrypt(text, secKey). Он был вызван дважды с text как str в первый раз, а как bytes во второй раз.

Решение состоит в том, чтобы убедиться, что вход text имеет str тип.

0 голосов
/ 24 февраля 2020

Поскольку первый параметр AES.new - это bytes / bytearray / memoryview, и я предполагаю, что text уже имеет тип bytes, то нам просто нужно преобразовать часть пэда из unicode в bytes .

text = text + (pad * chr(pad)).encode("utf-8")

Для большей безопасности вы можете условно кодировать text перед конкатенацией с pad.

if not isinstance(text, bytes):
    text = text.encode('utf-8')
...