16.2.1.5.1. Smartphone Container

class privacyidea.lib.containers.smartphone.SmartphoneContainer(db_container)[source]
check_challenge_response(params: dict) bool[source]
Checks if the response to a challenge is valid:
  • Challenge exists and is not expired

  • Equal scope

  • Valid signature

The message the client shall sign is a concatenation of the following values separated by ‘|’:
  • nonce (from the challenge)

  • timestamp (from the challenge)

  • serial of the container

  • scope: The URL the client wants to contact, e.g. “https://pi.net/container/register/finalize

  • ecc public key of the client in PEM format (optional)

  • container dict of the client (optional)

Parameters:

params – Dictionary with the parameters for the challenge. The device information is optional.

An example params dictionary:
{
    "signature": <sign(nonce|timestamp|serial|scope|pub_key|container_dict)>,
    "public_client_key_encry": <public key of the client for encryption base 64 url safe encoded>,
    "container_dict_client": {"serial": "SMPH0001", "type": "smartphone",
        "tokens": [{"serial": "1234", "type": "HOTP"}]...}
    "scope": "https://pi/container/SMPH001/sync",
    "device_brand": "XYZ",
    "device_model": "123"
}
Returns:

True if a valid challenge exists, raises a privacyIDEAError otherwise.

create_challenge(scope: str, validity_time: int = 2, data: dict = None) dict[str, str][source]

Create a challenge for the container.

Parameters:
  • scope – The scope (endpoint) of the challenge, e.g. “https://pi.com/container/SMPH001/sync

  • validity_time – The validity time of the challenge in minutes.

  • data – Additional data for the challenge.

Returns:

A dictionary with the challenge data in the format:

{
    "nonce": <nonce, str>,
    "time_stamp": <time stamp iso format, str>,
    "enc_key_algorithm": <encryption key algorithm, str>
}

encrypt_dict(container_dict: dict, params: dict) dict[source]

Encrypt a container dictionary.

Parameters:
  • container_dict – The container dictionary to be encrypted.

  • params – Dictionary with the parameters for the encryption from the client.

Returns:

Dictionary with the encrypted container dictionary and further encryption parameters

An example of a returned dictionary:
{
    "public_server_key": <public key of the server for encryption base 64 url safe encoded>,
    "encryption_algorithm": "AES",
    "encryption_params": {"mode": "GCM", "init_vector": "init_vector", "tag": "tag"},
    "container_dict_server": <encrypted container dict from server>
}
finalize_registration(params: dict) dict[str, bool][source]

Finalize the registration of a container. Validates whether the smartphone is authorized to register. If successful, the registration state is set as registered and the client public key is stored in the container info. Raises a ContainerInvalidSignature error if the signature is not valid.

The message the client shall sign is a concatenation of the following values separated by ‘|’:
  • nonce (from the registration challenge)

  • timestamp (from the registration challenge)

  • serial of the container

  • scope: The URL the client contacts to finalize the registration, e.g. “https://pi.net/container/register/finalize

  • device brand (optional)

  • device model (optional)

  • passphrase response if defined in the registration challenge

  • public key of the client in PEM format (curve secp384r1)

message = <nonce>|<time>|<serial>|<scope>|<device_brand>|<device_model>|<passphrase_response>|<public_key_client>

To verify the signature, the ECDSA signature algorithm with SHA256 hash function is used. The public key is expected to be an ecc key of curve secp384r1.

Parameters:

params – The parameters from the smartphone for the registration as dictionary like:

{
    "container_serial": <serial of the container, str>,
    "signature": <sign(message), str>,
    "public_client_key": <public key of the smartphone serialized in the PEM format>,
    "device_brand": <Brand of the smartphone, str> (optional),
    "device_model": <Model of the smartphone, str> (optional),
    "passphrase": <Passphrase of the user store, str> (optional)
}
Returns:

A dictionary with the success status like {"success": True}

classmethod get_class_description() str[source]

Returns a description of the container class.

classmethod get_class_prefix() str[source]

Returns the container class specific prefix for the serial.

classmethod get_class_type() str[source]

Returns the type of the container class.

classmethod get_supported_token_types() list[str][source]

Returns the token types that are supported by the container class.

get_tokens_for_synchronization() list[TokenClass][source]

Returns the tokens of the container that can be synchronized with a client as a list of TokenClass objects.

init_registration(server_url: str, scope: str, registration_ttl: int, ssl_verify: bool, params: dict = None) dict[source]

Initializes the registration: Generates a QR code containing all relevant data.

Parameters:
  • server_url – URL of the server reachable for the client.

  • scope – The URL the client contacts to finalize the registration e.g. “https://pi.net/container/register/finalize”.

  • registration_ttl – Time to live of the registration link in minutes.

  • ssl_verify – Whether the client shall use ssl.

  • params – Container specific parameters in the format:

{
    "passphrase_prompt": <str, the prompt for the passphrase displayed in the app>, (optional)
    "passphrase_response": <str, passphrase>, (optional)
    "passphrase_user": <bool, whether the passphrase shall be validated against the user store>, (optional)
    "extra_data": <dict, any additional data>, (optional)
}
Returns:

A dictionary with the registration data

An example of a returned dictionary:
{
    "container_url": {
        "description": "URL for privacyIDEA Container Registration",
        "value": <url>,
        "img": <qr code of the url>
    },
    "nonce": "ajhbdsuiuojno49877n4no3u09on38r98n",
    "time_stamp": "2020-08-25T14:00:00.000000+00:00",
    "key_algorithm": "secp384r1",
    "hash_algorithm": "SHA256",
    "ssl_verify": "True",
    "ttl": 10,
    "passphrase": <Passphrase prompt displayed to the user in the app> (optional)
}
classmethod is_multi_challenge_enrollable() bool[source]

Returns True if the container type can be enrolled during the authentication process “via multi challenge”

options = {'encrypt_algorithm': ['AES'], 'encrypt_key_algorithm': ['x25519'], 'encrypt_mode': ['GCM'], 'hash_algorithm': ['SHA256'], 'key_algorithm': ['secp384r1']}
terminate_registration()[source]

Terminate the synchronisation of the container with privacyIDEA. The associated information is deleted from the container info and all challenges for this container are deleted as well.