Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python: Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4

Tags:

python

decode

output the following error:

Exception Value:
Invalid base64-encoded string: number of data characters (5) cannot be 1 more than a multiple of 4
Exception Location: D:\Program Files\Python\lib\base64.py in b64decode, line 87 "

I input python like this :

key = hashlib.md5("exit_care".encode("ascii")).hexdigest().encode("ascii")
key_64 = base64.urlsafe_b64decode(key)
cipher_suite = Fernet(key_64)  
like image 257
faye rao Avatar asked Mar 11 '19 15:03

faye rao


3 Answers

Assuming you're using the Fernet class provided by the cryptography python package, you need to encode your key as base64 not decode it before passing it in. Encoding converts to the form specified, decoding converts from the form specified. What you're currently doing is converting exit_care to ascii (not necessary), computing the md5 hash, getting a hexidecimal representation, and converting that to ascii again. Then your program is trying to interpret that hexidecimal->ascii md5 hash as a base64-encoded string when you use base64.urlsafe_b64decode(key). This is the failure point at the moment. Likely you mean to use base64.urlsafe_b64encode(key) instead to convert it into the base64 required to use Fernet.

It's possible you may need to pad it to 32 bytes as the Fernet documentation suggests https://cryptography.io/en/latest/fernet/#cryptography.fernet.Fernet

Parameters: key (bytes) – A URL-safe base64-encoded 32-byte key. This must be kept secret. Anyone with this key is able to create and read messages.

This is because MD5 will produce a 128-bit value which is encoded as a 22 character base64 string (actually 24 because python automatically pads to a multiple of 4). See https://stackoverflow.com/a/13296298/6269138 as to why this is the case. Looking at the Fernet implementation, they check the length of the 64-bit-encoded string to see if its length is 32 and will error if it is not. You can right-pad with = if you want, or you can use a key-generating/key-stretching algorithm described below.

I recommend using a similar setup to the one on the Fernet documentation of the cryptograpy python package found here https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet for key-stretching. The code from the page is pasted below, swapping out PBKDF2HMAC with HKDF because the former requires a salt and is likely overkill for this situation as long as you aren't storing the passwords on a production database.

>>> import base64
>>> import os
>>> from cryptography.fernet import Fernet
>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives import hashes
>>> from cryptography.hazmat.primitives.kdf.hkdf import HKDF
>>> password = b"password"
>>> hkdf = HKDF(
...     algorithm=hashes.SHA256(),  # You can swap this out for hashes.MD5()
...     length=32,
...     salt=None,    # You may be able to remove this line but I'm unable to test
...     info=None,    # You may also be able to remove this line
...     backend=default_backend()
... )
>>> key = base64.urlsafe_b64encode(hkdf.derive(password))
>>> f = Fernet(key)
>>> token = f.encrypt(b"Secret message!")
>>> token
b'...'
>>> f.decrypt(token)  # Process the key in the exact same manner to decode an encoded message
b'Secret message!'
like image 169
Will T Avatar answered Oct 16 '22 05:10

Will T


This error happened to me after uninstalling Django==3.1.7 and installing Django==3.0.6 in my virtual environment. Clearing all the cookies in my browser and refreshing the page worked for me.

like image 3
Divine Avatar answered Oct 16 '22 05:10

Divine


  1. I think you have to update your pip

  2. you have install new django version

    python -m pip install --upgrade pip

    pip install django --upgrade

It works out for me, I create a new virtual environment and install all new upgraded packages, if your working with realtime big project, it have some constrain like this version django only needed, then you can check other answers, I am waiting for alternative for knowledge

You can also upgrade the specific django version if you need. pip install --upgrade django==1.6.5

like image 1
VigneshKarthik Kasiviswanathan Avatar answered Oct 16 '22 06:10

VigneshKarthik Kasiviswanathan