password_key

static EncryptHelper.password_key(password, salt=None, kdf: Type[cryptography.hazmat.primitives.kdf.KeyDerivationFunction] = <class 'cryptography.hazmat.primitives.kdf.pbkdf2.PBKDF2HMAC'>, **kwargs) → Tuple[str, dict][source]

Generate a cryptography.fernet.Fernet key based on a password and salt. Key derivation is customisable.

Parameters
  • password – A password to generate the key from, as str or bytes

  • salt – The salt to use when generating the key, as str or bytes If salt is a string, it can also be passed in base64 format.

Standard Usage with manual salt:

Call password_key with a password of your choice, and a salt of your choice (ideally at least 16 chars), and a tuple containing the Fernet key (base64 encoded), and key derivative configuration will be returned.

>>> ek = EncryptHelper
>>> key, kd = ek.password_key('MySecurePass', salt=b'Sup3rseCr3tsalt')
>>> key
'rJ_g-lBT7pxeu4MVrhfi5rAv9yLbX5pTm6vkJj_Mezc='
>>> kd
{'length': 32, 'salt': 'U3VwM3JzZUNyM3RzYWx0', 'backend': <...Backend object at 0x7fd1c0220eb8>,
'algorithm': <...SHA256 object at 0x7fd1b0232278>, 'iterations': 100000, 'kdf': <class '...PBKDF2HMAC'>}

You can see when we call the method a second time with the same password and salt, we get the same Fernet key.

>>> key, kd = ek.password_key('MySecurePass', salt=b'Sup3rseCr3tsalt')
>>> key
'rJ_g-lBT7pxeu4MVrhfi5rAv9yLbX5pTm6vkJj_Mezc='

Now we can simply initialise the class with this key, and start encrypting/decrypting data:

>>> enc = EncryptHelper(key)
>>> mydata = enc.encrypt_str('hello')
>>> mydata
'gAAAAABdsJrpZvQAhAEwAGk2GPeJMUjUdp1FHAg42ncArvvQjqGztLslgexF7dKWbJ8bhYNt9MBzzT0WR_XEvl1j5Q95UOVTsQ=='
>>> enc.decrypt_str(mydata)
'hello'

Automatic salt generation:

While it’s strongly recommend that you pass your own salt (at least 16 bytes recommended), for convenience this method will automatically generate a 16 byte salt and return it as part of the dict (second tuple item) returned.

First, we generate a key from the password helloworld

>>> ek = EncryptHelper
>>> key, kd = ek.password_key('helloworld')
>>> key
'6asAQ0qTQtmjw54RBR_RVmwsyv6EgTY_lcnVgJAVKCQ='
>>> kd
{'length': 32, 'salt': 'bDU5MzJaaEhnZ1htSmlQeg==', 'backend': <...Backend object at 0x7ff968053860>,
 'algorithm': <...SHA256 object at 0x7ff9685f6160>, 'iterations': 100000, 'kdf': <class '...PBKDF2HMAC'>}

If we call password_key again with helloworld, you’ll notice it outputs a completely different key. This is because no salt was specified, so it simply generated yet another salt.

>>> ek.password_key('helloworld')[0]
'BfesIzfEPodtHSyPrpnkK0iDipHikaE7T1uuFFPnqmc='

To actually get the same Fernet key back, we have to either:

  • Pass the entire kd dictionary as kwargs (safest option, contains all params used for generation)

    >>> ek.password_key('helloworld', **kd)[0]
    '6asAQ0qTQtmjw54RBR_RVmwsyv6EgTY_lcnVgJAVKCQ='
    
  • Pass the generated salt from the kd object, alongside our password.

    >>> ek.password_key('helloworld', salt=kd['salt'])[0]
    '6asAQ0qTQtmjw54RBR_RVmwsyv6EgTY_lcnVgJAVKCQ='