authnzerver.messaging module

This module handles the serialization-deserialization of messages between the authnzerver and any frontends.

authnzerver.messaging.chacha_decrypt_message(message: bytes, key: bytes, reqid: Union[str, int] = None, ttl: int = None) → Optional[dict][source]

Decrypts a ChaCha20-Poly1305-encrypted message back to a message dict.

This depends on OpenSSL containing the cipher, so OpenSSL > 1.1.0 probably. The version of the cipher used is the IETF-approved one (https://tools.ietf.org/html/rfc7539; with the 96-bit nonce).

Parameters:
  • message (bytes) – The encrypted message to decrypt.
  • key (bytes) – This is the 32-byte encryption key. Must be the same one as used for encrypting the message (i.e. this is a pre-shared secret key)
  • reqid (str or int or None) – A request ID used to track a decryption request. This will appear in any logging messages emitted by this function to allow tracking of requests and correlation.
  • ttl (int or None) – The age in seconds that the encrypted message must not exceed in order for it to be considered valid. This is useful for time-stamped verification tokens. If None, the message will not be checked for expiry.
Returns:

message_dict – Returns the decrypted message dict. If the message expired or if the message failed to decrypt because of an invalid key or if it was tampered with, returns None instead.

Return type:

dict or None

authnzerver.messaging.chacha_encrypt_message(message_dict: dict, key: bytes, nonce: bytes = None) → bytes[source]

Encrypts a dict using the ChaCha20-Poly1305 symmetric cipher.

This depends on OpenSSL containing the cipher, so OpenSSL > 1.1.0 probably. The version of the cipher used is the IETF-approved one (https://tools.ietf.org/html/rfc7539; with the 96-bit nonce).

Parameters:
  • message_dict (dict) – A dict containing items that will be encrypted.
  • key (bytes) –

    This is a 32-byte encryption key. Generate one using:

    import secrets
    key = secrets.token_bytes(32)
    
  • nonce (bytes or None) – This is a 12-byte nonce used for encryption. This MUST NOT be re-used with the same key if you want the message to remain secret. If None, a random 12-byte value will be used.
Returns:

encrypted_message – Returns the encrypted message as base64 encoded bytes.

Return type:

bytes

Notes

The encrypted message is generated in the following format:

base64(encrypt(<nonce><message dict + iat + ver>))
authnzerver.messaging.decrypt_message(message: bytes, key: bytes, reqid: Union[int, str] = None, ttl: int = None) → Optional[dict][source]

Decrypts a Fernet-encrypted message back to a message dict.

Parameters:
  • message (bytes) – The encrypted message to decrypt.
  • key (bytes) – This is the 32-byte encryption key in URL-safe base64 format. Must be the same one as used for encrypting the message (i.e. this is a pre-shared secret key)
  • reqid (str or int or None) – A request ID used to track a decryption request. This will appear in any logging messages emitted by this function to allow tracking of requests and correlation.
  • ttl (int or None) – The age in seconds that the encrypted message must not exceed in order for it to be considered valid. This is useful for time-stamped verification tokens. If None, the message will not be checked for expiry.
Returns:

message_dict – Returns the decrypted message dict. If the message expired or if the message failed to decrypt because of an invalid key or if it was tampered with, returns None instead.

Return type:

dict or None

authnzerver.messaging.encrypt_message(message_dict: dict, key: bytes) → bytes[source]

Encrypts a message dict using Fernet from the PyCA cryptography package.

Parameters:
  • message_dict (dict) – A dict containing items that will be encrypted.
  • key (bytes) –

    This is a 32-byte encryption key in URL-safe base64 format. Generate one using:

    import os, base64
    fernet_key = base64.urlsafe_b64encode(os.urandom(32))
    
Returns:

encrypted_message – Returns the encrypted message as base64 encoded bytes.

Return type:

bytes

authnzerver.messaging.xsalsa_decrypt_message(message: bytes, key: bytes, reqid: Union[int, str] = None, ttl: int = None) → Optional[dict][source]

Decrypts a XSalsa20-Poly1305-encrypted message back to a message dict.

This function requires PyNACL.

Parameters:
  • message (bytes) – The encrypted message to decrypt.
  • key (bytes) – This is the 32-byte encryption key. Must be the same one as used for encrypting the message (i.e. this is a pre-shared secret key)
  • reqid (str or int or None) – A request ID used to track a decryption request. This will appear in any logging messages emitted by this function to allow tracking of requests and correlation.
  • ttl (int or None) – The age in seconds that the encrypted message must not exceed in order for it to be considered valid. This is useful for time-stamped verification tokens. If None, the message will not be checked for expiry.
Returns:

message_dict – Returns the decrypted message dict. If the message expired or if the message failed to decrypt because of an invalid key or if it was tampered with, returns None instead.

Return type:

dict or None

authnzerver.messaging.xsalsa_encrypt_message(message_dict: dict, key: bytes) → bytes[source]

Encrypts a dict using the XSalsa20-Poly1305 symmetric cipher.

This function requires PyNACL.

Parameters:
  • message_dict (dict) – A dict containing items that will be encrypted.
  • key (bytes) –

    This is a 32-byte encryption key. Generate one using:

    import secrets
    key = secrets.token_bytes(32)
    
Returns:

encrypted_message – Returns the encrypted message as base64 encoded bytes.

Return type:

bytes