Декодирование Django urlsafe base64 с расшифровкой - PullRequest
18 голосов
/ 09 февраля 2010

Я пишу свою собственную систему кодирования для регистрации пользователей. Поэтому мне нужно создать подходящий URL для получения сгенерированных изображений с картинки. Поколение выглядит так:

_cipher = cipher.new(settings.CAPTCHA_SECRET_KEY, cipher.MODE_ECB)
_encrypt_block = lambda block: _cipher.encrypt(block + ' ' * (_cipher.block_size - len(block) % _cipher.block_size)) 
#...
a = (self.rightnum, self.animal_type[1])
serialized = pickle.dumps(a)
encrypted = _encrypt_block(serialized)
safe_url = urlsafe_b64encode(encrypted)

Но затем я пытаюсь получить этот ключ с помощью GET-запроса в функции представления, он завершается с ошибкой в ​​функции urlsafe_b64decode () с ошибкой «сопоставление символов должно возвращать целое число, нет или Unicode»:

def captcha(request):
  try:
    key = request.REQUEST['key']
    decoded = urlsafe_b64decode(key)
    decrypted = _decrypt_block(decoded)
    deserialized = pickle.loads(decrypted)
    return HttpResponse(deserialized)
  except KeyError: 
    return HttpResponseBadRequest()

Я обнаружил, что на выходе urlsafe_b64encode есть str, но GET-запрос возвращает объект Unicode (тем не менее, это правильная строка). Str () не помогло (возвращает ошибку декодирования глубоко внутри django), и если я использую ключ. repr , это работает, но расшифровщик не работает с ошибкой "Входные строки должны быть кратны 16 в длину ". Внутри тестового файла вся эта конструкция работает отлично, я не могу понять, что не так?

Ответы [ 2 ]

36 голосов
/ 09 февраля 2010

Проблема в том, что b64decode явно может принимать только байты (строку), а не юникод.

>>> import base64
>>> test = "Hi, I'm a string"
>>> enc = base64.urlsafe_b64encode(test)
>>> enc
'SGksIEknbSBhIHN0cmluZw=='
>>> uenc = unicode(enc)
>>> base64.urlsafe_b64decode(enc)
"Hi, I'm a string"
>>> base64.urlsafe_b64decode(uenc)
Traceback (most recent call last):
...
TypeError: character mapping must return integer, None or unicode

Поскольку вы знаете, что ваши данные содержат только данные ASCII (это то, что будет возвращать base64encode), должно быть безопасно кодировать ваши кодовые точки Unicode как байты ASCII или UTF-8, эти байты будут эквивалентны ожидаемому ASCII.

>>> base64.urlsafe_b64decode(uenc.encode("ascii"))
"Hi, I'm a string"
3 голосов
/ 09 февраля 2010

Я решил проблему!

deserialized = pickle.loads(captcha_decrypt(urlsafe_b64decode(key.encode('ascii'))))
return HttpResponse(str(deserialized))

Но я все еще не понимаю, почему это не сработало в первый раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...